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(clientSocket,(SOCKADDR*)&clientsock_in,strlen(SOCKADDR));//注意第三个参数

你别口口声声喊着第三个参数,结果给一个错的第三个参数,你运气好IPV4的addr和SOCKADDR长度一样,碰到IPV6你还传这个SOCKADDR,你就等死吧。

bind(clientSoc……

------解决方案--------------------
不是啊,客户端不需要bind,直接connect就行了。
------解决方案--------------------
用send发送心跳包。

探讨

引用:

不是啊,客户端不需要bind,直接connect就行了。


是这样的,上面一段代码是我连接服务器的逻辑,在连接之后我会进行一些操作,如果在操作的时候如何判断socket是否还在连接状态?如果发现断掉了,就重新连接呢?

------解决方案--------------------
服务端无法修改么?
如果是这样,我只能提供一个思路。
在另外的线程或者进程去检查这个socket是否可写。
可以参考select
或者还有其他的检测手段。
-
最好的办法是服务端也做修改。
客户端长时间的阻塞也不是很好。
虽然阻塞模式会让编码变的简单,但是扩展性会差很多。
如果本来就要实现很简单的功能,阻塞模式也是相当好的。
关键看需要用来解决什么问题。

探讨

引用:

如果处理数据会消耗时间很长(5min以上我觉得就比较长了,这个时间看需要更改)。
那么就可以考虑使用多线程,或者多进程,用另外的进程或线程处理数据。
如果再处理数据中,那么程序就无法保证一定连接。
或者另起线程或进程保证连接。
-
重连接的话最简单的方法:关闭现有的socket。重新建立socket。
引用:

引用 10 楼……

------解决方案--------------------
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
}