100分,SOCKET重新连接的有关问题
100分求助,SOCKET重新连接的问题
下面的代码是连接SOCKET服务器的代码,如何判断SOCKET是否断开?如果断开后自动重连的代码改如何写呢?
----------------------
string socket_ip = "127.0.0.1";
int socket_port = 19001;
if (err)
{
printf("客户端的嵌套字打开失败!\n");
return 0;//结束
}
SOCKET clientSocket=socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN clientsock_in;
clientsock_in.sin_addr.S_un.S_addr=inet_addr(socket_ip.c_str());
clientsock_in.sin_family=AF_INET;
clientsock_in.sin_port=htons(socket_port);
//bind(clientSocket,(SOCKADDR*)&clientsock_in,strlen(SOCKADDR));//注意第三个参数
//listen(clientSocket,5);
connect(clientSocket,(SOCKADDR*)&clientsock_in,sizeof(SOCKADDR));//开始连接
------------------
多谢?
------解决方案--------------------
//bind(clientSocket,(SOCKADDR*)&clientsock_in,strlen(SOCKADDR));//注意第三个参数
你别口口声声喊着第三个参数,结果给一个错的第三个参数,你运气好IPV4的addr和SOCKADDR长度一样,碰到IPV6你还传这个SOCKADDR,你就等死吧。
bind(clientSocket,(SOCKADDR*)&clientsock_in,sizeof(SOCKADDR_IN));
connect(clientSocket,(SOCKADDR*)&clientsock_in,sizeof(SOCKADDR_IN));//开始连接
------解决方案--------------------
楼上说的对。
-
如果连接断开,那么在recv或者send的时候就会失败,window的话可以调用WSAGetLastError(),查看错误代码。linux用errno。
------解决方案--------------------
CMySock::BindSock()
{
sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(4444);
int opt = 1;
int ret = setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR,
(const char*)&opt, sizeof(opt));
if (ret == SOCKET_ERROR)
return -1;
ret=bind(m_sock,(sockaddr *)&servaddr,sizeof(servaddr));
if (ret == SOCKET_ERROR)
int err = WSAGetLastError();
return 0;
}
------解决方案--------------------
WSAGetLastError()
------解决方案--------------------
------解决方案--------------------
不是啊,客户端不需要bind,直接connect就行了。
------解决方案--------------------
用send发送心跳包。
------解决方案--------------------
服务端无法修改么?
如果是这样,我只能提供一个思路。
在另外的线程或者进程去检查这个socket是否可写。
可以参考select
或者还有其他的检测手段。
-
最好的办法是服务端也做修改。
客户端长时间的阻塞也不是很好。
虽然阻塞模式会让编码变的简单,但是扩展性会差很多。
如果本来就要实现很简单的功能,阻塞模式也是相当好的。
关键看需要用来解决什么问题。
------解决方案--------------------
下面的代码是连接SOCKET服务器的代码,如何判断SOCKET是否断开?如果断开后自动重连的代码改如何写呢?
----------------------
string socket_ip = "127.0.0.1";
int socket_port = 19001;
if (err)
{
printf("客户端的嵌套字打开失败!\n");
return 0;//结束
}
SOCKET clientSocket=socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN clientsock_in;
clientsock_in.sin_addr.S_un.S_addr=inet_addr(socket_ip.c_str());
clientsock_in.sin_family=AF_INET;
clientsock_in.sin_port=htons(socket_port);
//bind(clientSocket,(SOCKADDR*)&clientsock_in,strlen(SOCKADDR));//注意第三个参数
//listen(clientSocket,5);
connect(clientSocket,(SOCKADDR*)&clientsock_in,sizeof(SOCKADDR));//开始连接
------------------
多谢?
------解决方案--------------------
//bind(clientSocket,(SOCKADDR*)&clientsock_in,strlen(SOCKADDR));//注意第三个参数
你别口口声声喊着第三个参数,结果给一个错的第三个参数,你运气好IPV4的addr和SOCKADDR长度一样,碰到IPV6你还传这个SOCKADDR,你就等死吧。
bind(clientSocket,(SOCKADDR*)&clientsock_in,sizeof(SOCKADDR_IN));
connect(clientSocket,(SOCKADDR*)&clientsock_in,sizeof(SOCKADDR_IN));//开始连接
------解决方案--------------------
楼上说的对。
-
如果连接断开,那么在recv或者send的时候就会失败,window的话可以调用WSAGetLastError(),查看错误代码。linux用errno。
------解决方案--------------------
CMySock::BindSock()
{
sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(4444);
int opt = 1;
int ret = setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR,
(const char*)&opt, sizeof(opt));
if (ret == SOCKET_ERROR)
return -1;
ret=bind(m_sock,(sockaddr *)&servaddr,sizeof(servaddr));
if (ret == SOCKET_ERROR)
int err = WSAGetLastError();
return 0;
}
------解决方案--------------------
WSAGetLastError()
------解决方案--------------------
------解决方案--------------------
不是啊,客户端不需要bind,直接connect就行了。
------解决方案--------------------
用send发送心跳包。
------解决方案--------------------
服务端无法修改么?
如果是这样,我只能提供一个思路。
在另外的线程或者进程去检查这个socket是否可写。
可以参考select
或者还有其他的检测手段。
-
最好的办法是服务端也做修改。
客户端长时间的阻塞也不是很好。
虽然阻塞模式会让编码变的简单,但是扩展性会差很多。
如果本来就要实现很简单的功能,阻塞模式也是相当好的。
关键看需要用来解决什么问题。
------解决方案--------------------
- C/C++ code
BOOL CTcpip::Tcp_ClientOpenInet(unsigned long ip, unsigned short port) { struct sockaddr_in server; int rval; unsigned long argp = 1; struct timeval tv; char errmsg[255]; fd_set fd; fd_set readfd; time_t t1, t2 ; unsigned char * p; memcpy(&(server.sin_addr), &ip, sizeof(server.sin_addr)); server.sin_port = htons(port); server.sin_family = AF_INET; clisock = socket(AF_INET, SOCK_STREAM, 0); if (clisock < 0) { /* sockid == -1 */ sprintf(errmsg, "Client: socket() create. with error %d", WSAGetLastError()); DebugLog(errmsg); return FALSE; } ioctlsocket(clisock, FIONBIO, &argp); FD_ZERO(&fd); FD_ZERO(&readfd); time(&t1) ; t2 = t1 + 5 ; while (WaitForSingleObject(gReadDataEvent, 30) != WAIT_OBJECT_0) { rval = connect(clisock, (struct sockaddr *) &server, sizeof(server)) ; if (rval != 0) { FD_SET(clisock, &fd); tv.tv_sec = 0; //gwcfg.timeout; tv.tv_usec =5000L; //500000L; FD_SET(clisock, &readfd); tv.tv_sec = 0; tv.tv_usec = 5000L; if ((rval = select(0, &readfd, &fd, NULL, &tv)) <= 0) { if (rval == SOCKET_ERROR) { int Error = WSAGetLastError(); switch(Error) { case WSANOTINITIALISED: break; case WSAEFAULT: //currently ignore this condition TRACE(_T("WARNING: MAX. Message Size exceeded\n")); break; case WSAENETDOWN: break; default: { TCHAR buffer[512]; wsprintf(buffer, _T("SendTo() returned %d"), Error); } break; } } time(&t1) ; if (t1 > t2) { /* time out */ closesocket(clisock); p = (unsigned char *) &ip; return FALSE ; } } else { argp = 0; // none block if (!AsyncMode) ioctlsocket(clisock, FIONBIO, &argp); return TRUE; } } else { argp = 0; // none block if (!AsyncMode) ioctlsocket(clisock, FIONBIO, &argp); return TRUE; } } return FALSE; #endif }