客户侧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;
}
浙公网安备 33010602011771号