请问:client 正在connect()的时候,如何取消连接请求?就像MSN,QQ的登陆一样,正在登陆的时候用户是可以随时“取消登陆”的,但此时程序一般都是在connect()服务器啊,在没有知道是否登陆成功的时候如何断开SOCKET呢?

解决方案 »

  1.   

    你自己开一个线程出来Connect吧.你关闭了主程序的时候,这个线程也会自己关掉的了.
      

  2.   

    SOCKET有自己的关闭函数:
    该函数的原型为:
    int shutdown( SOCKET s, int how );
    其中how的取值为:SD_RECEIVE、SD_SEND或SD_BOTH,若是SD_RECEIVE就表示不允许在调用接收函数,这对底部的协议层没影响,若是SD_SEND表示不在调用发送,最后参数表示取消2端的操作。
    注意:该函数并不关闭套接字,并且套接字的资源一直保持到closesocket()调用。
    另外一个函数是:closesocket( SOCKET s )这个才是真正的关闭SOCKET。
      

  3.   

    // BdSockEx.cpp: implementation of the CBdSockEx class.
    //
    //////////////////////////////////////////////////////////////////////#include "stdafx.h"
    #include "BdSockEx.h"#pragma comment(lib,"Ws2_32.lib")
    //////////////////////////////////////////////////////////////////////
    // Construction/Destruction
    //////////////////////////////////////////////////////////////////////CBdSockEx::CBdSockEx()
    {
    Reset(); 
    }CBdSockEx::CBdSockEx(SOCKET Socket)
    {
    Reset(); 
    m_Socket=Socket;
    }CBdSockEx::~CBdSockEx()

    }bool CBdSockEx::Startup(void) 
    {
    WSADATA       wsd;
    if (WSAStartup(MAKEWORD(1,1), &wsd) != 0)
        {
            AfxMessageBox("Failed to load Winsock library!\n");
            return false;
        }
    return true;
    }void CBdSockEx::Cleanup(void)
    {
    WSACleanup();
    }bool CBdSockEx::IsConnected(void)

    return(m_nStatus==BDSOCK_STAT_CONNECTED);
    }bool CBdSockEx::IsDisConnected(void)
    {
    return(m_dwErrNo==BDSOCK_ERRNO_DISCONNECT);
    }void CBdSockEx::Reset(void)
    {
    m_dwErrNo=BDSOCK_ERRNO_NONE;
    m_dwSubErrNo=BDSOCK_ERRNO_NONE;
    m_nStatus=BDSOCK_STAT_NOCONNECT; 
    m_Socket=INVALID_SOCKET; 
    }bool CBdSockEx::Create(void)
    {
        m_Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

        if(m_Socket==INVALID_SOCKET)
    {
    m_dwErrNo=BDSOCK_ERRNO_CREATE; 
    return false;


    //设为非阻塞
    u_long  ofcmode=1;
    if(ioctlsocket(m_Socket,FIONBIO,&ofcmode) ) 
        {
    m_dwErrNo=BDSOCK_ERRNO_CREATE; 
    return false;
        }


    return true; 
    }int CBdSockEx::SignalSafeSelect(int nfds, fd_set * rs, fd_set * ws, fd_set * es,struct timeval *tv)
    {
    int rv;

    while ((rv = select (nfds, rs, ws, es, tv)) < 0)
        {
    int nError=WSAGetLastError();
    if(nError!=WSAEINTR) 
    break;
        }
    return rv;
    }void CBdSockEx::MsToTimeval (const int ms, struct timeval *tv)
    {
    tv->tv_sec = ms / TIME_CNV_RATIO;
    tv->tv_usec = (ms - tv->tv_sec * TIME_CNV_RATIO) * TIME_CNV_RATIO;
    }bool CBdSockEx::Connect(char * szIpAddr,UINT nPort,int nSec)
    {
    struct sockaddr_in  srvaddr;

    memset(&srvaddr,0x00,sizeof(srvaddr));
    srvaddr.sin_family = AF_INET;
        srvaddr.sin_port = htons(nPort);
        srvaddr.sin_addr.s_addr = inet_addr(szIpAddr);
        

    int retcode = connect(m_Socket, (struct sockaddr*)&srvaddr, sizeof(srvaddr));
    if(retcode==0)
    { //超时处理  
    AfxMessageBox("retcode==0\n");
    return false;
    }

        /*******
    int nError=WSAGetLastError();
    printf("nError=%ld\n",nError);
    if(nError!=WSAEWOULDBLOCK)
    {
    return false; 
    }
    *********/

    struct timeval tv;
    fd_set readfds,writefds;

    tv.tv_sec = nSec;  //设置时间为5秒 
    tv.tv_usec = 0; 

    FD_ZERO(&readfds);
    FD_ZERO(&writefds);
    FD_SET(m_Socket,&writefds);


    retcode =SignalSafeSelect(m_Socket+1,0, &writefds,0, &tv); 
    if (retcode < 0)
    {  //select返回错误??? 
    //错误处理 
    m_dwErrNo=BDSOCK_ERRNO_CONNECT; 
    return false;

    else if(0 == retcode) 
    {  //超时处理 
            AfxMessageBox("connect timeout!\n");
    m_dwErrNo=BDSOCK_ERRNO_CONNECT; 
    return false;


        //套接字已经准备好
    if ( !FD_ISSET(m_Socket, &readfds) && !FD_ISSET(m_Socket, &writefds)) 

    AfxMessageBox("!FD_ISSET(m_Socket, &readfds) && !FD_ISSET(m_Socket, &writefds)\n");
    m_dwErrNo=BDSOCK_ERRNO_CONNECT; 
    return false;
    }

    int err,len=sizeof(int);
    if (getsockopt(m_Socket, SOL_SOCKET, SO_ERROR, (char *)&err, &len) < 0) 

    AfxMessageBox("getsockopt(m_Socket, SOL_SOCKET, SO_ERROR, (char *)&err, &len) < 0\n");
    m_dwErrNo=BDSOCK_ERRNO_CONNECT; 
    return false; 
    }
    if (err != 0) 

    AfxMessageBox("err !=0\n");
    m_dwErrNo=BDSOCK_ERRNO_CONNECT; 
    return false;  

    AfxMessageBox("connect return ok!\n");
    m_nStatus=BDSOCK_STAT_CONNECTED;

        return true; 

    }void CBdSockEx::Close(void)
    {
    if(m_Socket!=INVALID_SOCKET)
    {
    if(m_nStatus==BDSOCK_STAT_CONNECTED)
    {
    shutdown(m_Socket,SD_BOTH);
    }
    closesocket(m_Socket); 
    }
    Reset(); 
    }int CBdSockEx::Read(char * szBuf,int nLength,int msec)
    {
    struct timeval tv;
    fd_set readfds;
    MsToTimeval (msec, &tv);

        FD_ZERO(&readfds);

    FD_SET(m_Socket,&readfds); 

    int retcode =SignalSafeSelect(m_Socket+1,&readfds,0,0, &tv); 
    if (retcode < 0)
    {
    AfxMessageBox("read select<0\n");
    return 0;

    else if(0 == retcode) 
    {   
    AfxMessageBox("read select=0\n");
    return 0;
    }

    if(FD_ISSET(m_Socket,&readfds)) 
    {  
    int nRet=recv(m_Socket,szBuf,nLength,0);
    if(nRet>0)

    szBuf[nRet]=0x00;
    return nRet;
    }
    int nError=WSAGetLastError();
    if(nError!=WSAEINTR || (nRet==0)) 
    {
    m_dwErrNo=BDSOCK_ERRNO_DISCONNECT;    
    return -1;
    }
    AfxMessageBox("read ret %d  error=%d\n",nRet,nError); 
    return 0; 
    }

    m_dwErrNo=BDSOCK_ERRNO_DISCONNECT;    
    return -1; 
    }int CBdSockEx::Write(char * szBuf,int nLength,int msec)
    {
    struct timeval tv;
    fd_set writefds;
    MsToTimeval (msec, &tv);

    FD_ZERO(&writefds); 
    FD_SET(m_Socket,&writefds); 

    int retcode =SignalSafeSelect(m_Socket+1,0,&writefds,0, &tv); 
    if (retcode < 0)
    {   
    AfxMessageBox("write select<0\n");
    return 0;

    else if(0 == retcode) 

    AfxMessageBox("write select=0\n");
    return 0;
    }


    if (FD_ISSET(m_Socket,&writefds)) 
    {

    int wc = send (m_Socket,szBuf,nLength,0);
    if(wc>0)

    return wc;
    }
    int nError=WSAGetLastError();
    if(nError!=WSAEINTR || (wc==0)) 
    {
    m_dwErrNo=BDSOCK_ERRNO_DISCONNECT;    
    return -1;

    AfxMessageBox("write error=%d\n",nError);
    return 0;

    m_dwErrNo=BDSOCK_ERRNO_DISCONNECT;    
    return -1;  
    }
    SOCKET CBdSockEx::Accept(
     struct sockaddr FAR * cliaddr,//ip地址
     int FAR * addrlen,
     int nSec
     )

    int n;
    fd_set rset; 
    SOCKET socket=INVALID_SOCKET;

    struct timeval tv; 
    tv.tv_sec=nSec;
    tv.tv_usec=0;

    FD_ZERO (&rset);
    FD_SET(m_Socket,&rset);
    n = SignalSafeSelect(m_Socket+ 1, &rset, NULL, NULL, &tv);
    if(n < 0)
    {
    m_dwErrNo=BDSOCK_ERRNO_ACCEPT;    
    return INVALID_SOCKET;
    }
    if (FD_ISSET(m_Socket, &rset))
    {  
    while ((socket = accept(m_Socket, cliaddr, addrlen))==INVALID_SOCKET)
    {
    int nError=WSAGetLastError();  
    if (nError != WSAEWOULDBLOCK && nError!= WSAECONNABORTED && nError!= WSAEINTR)
    {
    m_dwErrNo=BDSOCK_ERRNO_ACCEPT;
    break;
    }
    }
    }

    return socket;
    }bool CBdSockEx::Listen(int nMaxClient)

    int nRet=listen(m_Socket,nMaxClient);
    if(nRet== SOCKET_ERROR)
    {
    m_dwErrNo=BDSOCK_ERRNO_LISTEN;
    return false;
    }
    return true;
    }bool CBdSockEx::Bind(char * szLocalIpAddr,UINT nPort)
    {
    sockaddr_in service;
    service.sin_family = AF_INET;
    service.sin_addr.s_addr = inet_addr(szLocalIpAddr);
    service.sin_port = htons(nPort);

    if(bind(m_Socket,(SOCKADDR*) &service,sizeof(service)) == SOCKET_ERROR) 
    {
    int nError=WSAGetLastError();
    printf("nError=%d\n",nError);
    m_dwErrNo=BDSOCK_ERRNO_BIND;
    return false;
    }
    return true;

    }
      

  4.   

    // BdSockEx.h: interface for the CBdSockEx class.
    //
    //////////////////////////////////////////////////////////////////////#if !defined(AFX_BDSOCKEX_H__7B57E28E_05F0_5688_956AD_B93BC30025F897__INCLUDED_)
    #define AFX_BDSOCKEX_H__7B57E28E_05F0_5688_956AD_B93BC30025F897__INCLUDED_#if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    #include <winsock2.h>#define TIME_CNV_RATIO 1000
     
    class CBdSockEx  
    {
    private:
    SOCKET m_Socket;public:
    CBdSockEx();
    CBdSockEx(SOCKET Socket);
    virtual ~CBdSockEx(); unsigned long m_dwErrNo; //错误码
    unsigned long m_dwSubErrNo;
    int   m_nStatus; //连接状态 static bool Startup(void);
    static void Cleanup(void);
    void Reset(void);
    bool IsConnected(void);
    bool IsDisConnected(void); bool Create(void); 
    void Close(void);

    bool Bind(char * szLocalIpAddr,UINT nPort);
    bool Listen(int nMaxClient=5);  
    SOCKET Accept(struct sockaddr FAR * cliaddr,int FAR * addrlen,int nSec=3); bool Connect(char * szIpAddr,UINT nPort,int nSec=5); int  Read(char * szBuf,int nLength,int msec=50);
    int  Write(char * szBuf,int nLength,int msec=50);private:
    int SignalSafeSelect(int nfds, fd_set * rs, fd_set * ws, fd_set * es,struct timeval *tv);
    void MsToTimeval(const int ms, struct timeval *tv);
    }; #endif // !defined(AFX_BDSOCKEX_H__7B57E28E_05F0_5688_956AD_B93BC30025F897__INCLUDED_)
      

  5.   

    看来没理解我的意思,我是说,正在CONNECT的时候怎么取消CONNECT,异步非阻塞模式下
      

  6.   

    异步好办,closesocket()"登陆" != socket connect"登陆"是用户信息的交换,是connect完成以后的事情!