如下实现多线程阻塞SOCKET AcceptSocket;
SOCKADDR_IN addrClient;
int addrClientLen = sizeof(SOCKADDR);
printf("Waiting for client to connect...\n");
while(1) {
if( (AcceptSocket = accept( ListenSocket1, (SOCKADDR *)&addrClient, &addrClientLen)) != SOCKET_ERROR ) {
ConnectInfor * conInf = new ConnectInfor();
conInf->addrClient = addrClient;
conInf->sock = AcceptSocket;
CreateThread(NULL,0,SocketThread,(LPVOID)conInf,0,NULL);
} }线程代码DWORD WINAPI SocketThread(LPVOID lpmess)
{
ConnectInfor * conInf = (ConnectInfor *)lpmess;
char conType;
int bytesRecv;
bytesRecv = getByte(conInf->sock,conType);
if ( bytesRecv <= 0 || bytesRecv == WSAECONNRESET ) {
return 0;
} switch(conType)
{
case CAMERA:
cameraNet(conInf);
break;
case PLAYER:
playerNet(conInf);
break;
} closesocket(conInf->sock);
printf("close sock\n");
delete conInf;
return 0; //最后不要忘记返回一个DWORD
}
现有客户端1
send一个字节,再recv255个字节,然后closesocket客户端2
循环 send一个字节,再recv255个字节。
服务器对应处理代码为void cameraNet(ConnectInfor * conInf)
{
SOCKET ListenSocket = conInf->sock;
char sendbuf[32] = "Server: Sending data.";
char recvbuf[32] = ""; int bytesSent;
int bytesRecv = SOCKET_ERROR;
printf("camera connect\n");
Camera camera ;
camera.getCameraInf(conInf);
connectCameraList[camera.id] = camera;
while(true)
{
char b;
bytesRecv = getByte(ListenSocket,b);
if ( bytesRecv <= 0 || bytesRecv == WSAECONNRESET ) {
break;
} switch(b)
{
case 100:
{
bytesSent = send( ListenSocket, sendbuf, strlen(sendbuf), 0 );
bytesRecv = recv( ListenSocket, recvbuf, 32, 0 );
if ( bytesRecv <= 0 || bytesRecv == WSAECONNRESET ) {
printf( "Bytes Recv from %d(ip = %s:%d): Connection Closed\n",ListenSocket,inet_ntoa(conInf->addrClient.sin_addr),htons(conInf->addrClient.sin_port) );
break;
}
printf("from client recive: %s\n",recvbuf);
}
break;
}
Sleep(0);
}
printf("camera desconnect\n");
connectCameraList.erase(camera.id);
}
现象:
只启动n个客户端1,工作正常(这是当然的)
启动n个客户端2,第一个正常,第二个以上不能连接。
启动1个客户端2,再启动一个客户端1,工作正常,但再启动一个客户端2,也连接失败。
请问问题有可能出现在哪里呢?
是不是对应循环发送消息的线程需要将socket休眠之类的?
SOCKADDR_IN addrClient;
int addrClientLen = sizeof(SOCKADDR);
printf("Waiting for client to connect...\n");
while(1) {
if( (AcceptSocket = accept( ListenSocket1, (SOCKADDR *)&addrClient, &addrClientLen)) != SOCKET_ERROR ) {
ConnectInfor * conInf = new ConnectInfor();
conInf->addrClient = addrClient;
conInf->sock = AcceptSocket;
CreateThread(NULL,0,SocketThread,(LPVOID)conInf,0,NULL);
} }线程代码DWORD WINAPI SocketThread(LPVOID lpmess)
{
ConnectInfor * conInf = (ConnectInfor *)lpmess;
char conType;
int bytesRecv;
bytesRecv = getByte(conInf->sock,conType);
if ( bytesRecv <= 0 || bytesRecv == WSAECONNRESET ) {
return 0;
} switch(conType)
{
case CAMERA:
cameraNet(conInf);
break;
case PLAYER:
playerNet(conInf);
break;
} closesocket(conInf->sock);
printf("close sock\n");
delete conInf;
return 0; //最后不要忘记返回一个DWORD
}
现有客户端1
send一个字节,再recv255个字节,然后closesocket客户端2
循环 send一个字节,再recv255个字节。
服务器对应处理代码为void cameraNet(ConnectInfor * conInf)
{
SOCKET ListenSocket = conInf->sock;
char sendbuf[32] = "Server: Sending data.";
char recvbuf[32] = ""; int bytesSent;
int bytesRecv = SOCKET_ERROR;
printf("camera connect\n");
Camera camera ;
camera.getCameraInf(conInf);
connectCameraList[camera.id] = camera;
while(true)
{
char b;
bytesRecv = getByte(ListenSocket,b);
if ( bytesRecv <= 0 || bytesRecv == WSAECONNRESET ) {
break;
} switch(b)
{
case 100:
{
bytesSent = send( ListenSocket, sendbuf, strlen(sendbuf), 0 );
bytesRecv = recv( ListenSocket, recvbuf, 32, 0 );
if ( bytesRecv <= 0 || bytesRecv == WSAECONNRESET ) {
printf( "Bytes Recv from %d(ip = %s:%d): Connection Closed\n",ListenSocket,inet_ntoa(conInf->addrClient.sin_addr),htons(conInf->addrClient.sin_port) );
break;
}
printf("from client recive: %s\n",recvbuf);
}
break;
}
Sleep(0);
}
printf("camera desconnect\n");
connectCameraList.erase(camera.id);
}
现象:
只启动n个客户端1,工作正常(这是当然的)
启动n个客户端2,第一个正常,第二个以上不能连接。
启动1个客户端2,再启动一个客户端1,工作正常,但再启动一个客户端2,也连接失败。
请问问题有可能出现在哪里呢?
是不是对应循环发送消息的线程需要将socket休眠之类的?
解决方案 »
- 用vc编程对word操作!
- 关于debug和release的问题
- system.xml.dll 和 msxml6.dll 是什么关系
- double 轉CString?
- 在当前对话框中编辑代码时为什么获取当前对话框的指针会出错
- 可以推荐几个网站可以下载vc源代码研究的网站啊?谢谢
- 问VC++中文版帮助何处有?不知是否有人告诉我!
- 那位大虾可以提供一个免费的、好用的报表控件,我都快急死了!
- 请教各位大虾一个easy问题:如何创建一个无模式的propertysheet,要求用CPropertySheet类实现
- 怎么获取图片的大小及颜色?
- _ConnectionPtr.Create()总是失败呢?
- Fn+按键 有对应的按键消息么?
因为要实现TCP穿越,connect之前必须将几个socket绑定在一个固定端口上。sockaddr_in server;
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr( "127.0.0.1" );
server.sin_port = htons( 27015 ); sockaddr_in myAddress;
myAddress.sin_family = AF_INET;
myAddress.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
myAddress.sin_port = htons( C_SERVER_LISTEN_POINT );
int flag=1,len=sizeof(int); setsockopt(ConnectSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&flag, sizeof(flag)); if (bind( ConnectSocket,
(SOCKADDR*) &myAddress,
sizeof(myAddress)) == SOCKET_ERROR) {
printf("bind() failed.\n");
closesocket(ConnectSocket);
return;
}
//----------------------
// Connect to server.
if ( connect( ConnectSocket, (SOCKADDR*) &server, sizeof(server) ) == SOCKET_ERROR) {
printf( "Failed to connect.\n" );
WSACleanup();
return;
}上面setsockopt(ConnectSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&flag, sizeof(flag)); if (bind( ConnectSocket,
(SOCKADDR*) &myAddress,
sizeof(myAddress)) == SOCKET_ERROR) {
printf("bind() failed.\n");
closesocket(ConnectSocket);
return;
} 去掉了就正常了。
但是做TCP穿越必须用端口复用技术,在一个进程中将多个socket绑定在一个端口上。但多了以上代码多线程加阻塞就出问题了。请做过TCP穿越的前辈给给经验。
{
//----------------------
// Initialize Winsock
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR)
printf("Error at WSAStartup()\n"); //----------------------
// Create a SOCKET for connecting to server
SOCKET ConnectSocket;
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET) {
printf("Error at socket(): %ld\n", WSAGetLastError());
WSACleanup();
return false;
} //----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server to be connected to.
sockaddr_in server;
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr( "127.0.0.1" );
server.sin_port = htons( 27015 ); sockaddr_in myAddress;
myAddress.sin_family = AF_INET;
myAddress.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
myAddress.sin_port = htons( C_SERVER_LISTEN_POINT );
int flag=1,len=sizeof(int); setsockopt(ConnectSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&flag, sizeof(flag)); if (bind( ConnectSocket,
(SOCKADDR*) &myAddress,
sizeof(myAddress)) == SOCKET_ERROR) {
printf("bind() failed.\n");
closesocket(ConnectSocket);
WSACleanup();
return false;
}
//----------------------
// Connect to server.
if ( connect( ConnectSocket, (SOCKADDR*) &server, sizeof(server) ) == SOCKET_ERROR) {
printf( "Failed to connect.\n" );
WSACleanup();
return false;
} //----------------------
// Declare and initialize variables.
int bytesSent;
int bytesRecv = SOCKET_ERROR;
char sendbuf[32] = "Client: Sending data.";
char recvbuf[32] = "";
char cameraId[255] = "test id"; sendByte(CAMERA,ConnectSocket);
bytesSent = send( ConnectSocket, cameraId, 255, 0 );
printf( "Bytes Sent: %ld\n", bytesSent ); sendByte(CAMERA_REGISTER,ConnectSocket);
while(true)
{ /*sendInt(100,ConnectSocket);*/
sendByte(100,ConnectSocket);
bytesRecv = recv( ConnectSocket, recvbuf, 32, 0 );
if ( bytesRecv <= 0 || bytesRecv == WSAECONNRESET ) {
printf( "Connection Closed.\n");
break; }
printf( "Bytes Recv: %ld %s\n", bytesRecv,recvbuf );
bytesSent = send( ConnectSocket, sendbuf, strlen(sendbuf), 0 );
printf( "Bytes Sent: %ld\n", bytesSent );
Sleep(3000);
} closesocket(ConnectSocket); WSACleanup();
return true;
}
void main() {
while(!tcpConnect())
{
printf("using port %d false \n",C_SERVER_LISTEN_POINT);
C_SERVER_LISTEN_POINT++;
printf("try port %d false \n",C_SERVER_LISTEN_POINT);
}
}方法比较笨拙,呵呵