客户侧tcp连接的建立

int TcpConnect(char* hostname, int port)
{

struct sockaddr_in dest;

fd_set writefds;
struct timeval timeout;

int id=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (id<0)
{
  perror("create socket error");
}

// 禁用Nagle算法,即发送不缓存
int flag = 1;
if (setsockopt(id, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag)) < 0)

{
  perror("setsockopt of TCP_NODELAY error");
}

// 地址可重用,不用等待time_wait状态的改变
int on=1;
setsockopt(id, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));

// 设置为不阻塞通信
for (;;)
{
#ifdef UNIX
  on=1;
  if (ioctlsocket(id, FIONBIO, (char *)&on) < 0)
#endif

#ifdef WIN32
  unsigned long on_windows=1;
  if (ioctlsocket(id, FIONBIO, &on_windows) < 0)
#endif

  {

    if (GET_LAST_SOCK_ERROR() == EINTR)
      continue;

    closesocket(id);
    return -1;
  }
  break;
}

dest.sin_family = AF_INET;
dest.sin_port = htons(port);

if (isalpha(hostname[0]))   // www.xxx

  hostent *pHostent=gethostbyname(hostname);
  if (pHostent==NULL)
  {
    return -1;
  }
  memcpy(&(dest.sin_addr.s_addr),pHostent->h_addr,pHostent->h_length);
}
else
{
  dest.sin_addr.s_addr=inet_addr(hostname); 
}
/* try to connect it */
int ret=::connect(id,(struct sockaddr *)&dest,sizeof(dest));

// 连接成功,则返回该socketid
if (ret==0)
{
  return id;
}

/* use select to wait for it */
FD_ZERO(&writefds);
FD_SET(id,&writefds);
timeout.tv_sec=5;
timeout.tv_usec=0;
ret=select(id+1,NULL,&writefds,NULL,&timeout);

/* timeout? then return with fail */
if (ret==0)
{
  closesocket(id);
  return -1;
}

/* recheck whether connected */
struct sockaddr name;
if ((ret>0)&&FD_ISSET(id,&writefds))
{
  SOCKADDRLEN nameLen=sizeof(name);
  if (getpeername(id,&name,&nameLen)==0)
  {
    return id;
  }
}
closesocket(id);

return -1;

}

posted on 2016-09-20 15:16  Offen_Lou  阅读(121)  评论(0)    收藏  举报

导航