天天看點

libevent異步TCP連接配接,判斷是否連接配接成功



libevent異步TCP連接配接伺服器的過程:

1)建立nonblock的socket,

2)調用connect連接配接伺服器,檢查傳回值,判斷是否是阻塞了,如果是,就設定等待 EV_WRITE事件:

     event_set(&m_evSocket, m_iSockFd, EV_WRITE, onConnect, this);

3)EV_WRITE傳回後,判斷event是否為EV_WRITE,

關鍵一點:如果EV_WRITE,還要進一步判斷sockopt是否正确。

代碼片段如下:

bool CClientSocket::connectSocket(string szHostAddr, int nHostPort){
 if (m_iSockFd == -1){
  createSocket();
 }

 struct sockaddr_in Ser_addr;
 memset(&Ser_addr, 0, sizeof(struct sockaddr_in));

 Ser_addr.sin_family = AF_INET;
 Ser_addr.sin_addr.s_addr = inet_addr(szHostAddr.c_str());
 Ser_addr.sin_port = htons(nHostPort);

 if(connect(m_iSockFd, (const struct sockaddr *) &Ser_addr,sizeof(Ser_addr)) == -1){ 
  if ( errno == EINPROGRESS || errno == EWOULDBLOCK){
   event_set(&m_evSocket, m_iSockFd, EV_WRITE, onConnect, this);
   event_base_set(&m_eventbase, &m_evSocket);
   struct timeval tv1;
   tv1.tv_sec = 5;
   tv1.tv_usec = 0;
   event_add(&m_evSocket, &tv1);
   m_connSCRStatus.sockRequestSended();
   printf("connect would block\n");
   return true;
  }
  else{     
   printf("fail to connect\n");
   closeSocket();
   return false;
  }
 }
 else{
  printf("connected directly...\n");
  // connected directlly
  event_set(&m_evSocket, m_iSockFd, EV_READ|EV_PERSIST, onRecv, this); 
  event_base_set(&m_eventbase, &m_evSocket);
  event_add(&m_evSocket, NULL);
  onConnect(); 
  return true;
 }

}

void CClientSocket::onConnect(int fd, short event, void *arg){
 CClientSocket *pThis = (CClientSocket*)arg;
 if (event == EV_WRITE){ 
  int err;
  socklen_t len = sizeof(err);
  getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &len);
  if (err) {
   printf("connect return ev_write, but check failed\n");
   pThis->closeSocket();
  }
  else{
   event_set(&pThis->m_evSocket, pThis->m_iSockFd, EV_READ|EV_PERSIST, onRecv, arg);
   event_base_set(&pThis->m_eventbase, &pThis->m_evSocket);
   event_add(&pThis->m_evSocket, NULL);
   pThis->onConnect();
   printf("connect return ev_write, check ok\n");
  }
 }
 else{  // timeout
  printf("connect return failed\n");
  pThis->closeSocket();
 }
}

void CClientSocket::onConnect(){
 logMessage("connect ok!");
 //

}
           

參考:

http://stackoverflow.com/questions/16074981/how-to-check-if-connection-is-established-when-use-libev-with-non-block-socket

繼續閱讀