// Tcp.h: 基本网络通讯封装类
//
//////////////////////////////////////////////////////////////////////
#ifndef __TCP_H__
#define __TCP_H__
#include
#pragma comment(lib, "wsock32.lib") // search for wsock32 lib at compile time
#define WM_TCP WM_APP+100
class CTcp
{
public:
CTcp();
~CTcp();
//extern int sd_connect, sd_bind, sd_accept;
int wsa_ok ;
static void peek_message(void);
static int get_local_ip(char *ip);
int init();
int exit();
int bind_listen(int port,sockaddr_in& addr,long &err);
int status(int sd, char *type, int timeout=5);
int bind(HWND hWnd, int port);
int bind2(HWND hWnd, char *ip, int port);
int accept(int sd, int timeout);
int connect(char *hostname, int port, int timeout, int f_noblock);
int connect2(char *bind_ip, char *hostname, int port, int timeout, int f_noblock);
void disconnect(int sd);
void close(int& sd);
int send(int sd, char *buf, int len, int timeout=10);
int recv(int sd, char *buf, int len, int timeout=10);
int gethostnamebyip(char *ip, char *name);
unsigned short htons(unsigned short);
unsigned short ntohs(unsigned short);
unsigned long int htonl(unsigned long int);
unsigned long int ntohl(unsigned long int);
unsigned __int64 ntohh(unsigned __int64);
unsigned __int64 htonh(unsigned __int64);
float htonf(float f);
float ntohf(float f);
double htond(double d);
double ntohd(double d);
char *get_remote_ip(int sd, char *ip);
};
#endif
------------------------------------------------------
// Tcp.cpp: implementation of the CTcp class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include
#include
#include
#include
#include "tcp.h"
extern WriteLog(char *file_name, char *format, ...);
extern WriteStat(char *format, ...);
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CTcp::CTcp()
{
wsa_ok =0;
}
CTcp::~CTcp()
{
}
int CTcp::init()
{
if(!wsa_ok)
{
WSAData wsa;
//sd_bind =sd_connect =sd_accept =-1;
if(WSAStartup(MAKEWORD(1, 1), &wsa) !=0)
return -1;
wsa_ok =1;
}
return 0;
}
int CTcp::exit()
{
if(wsa_ok) WSACleanup();
return 0;
}
int CTcp::status(int sd, char *type, int timeout)
{
fd_set rset, wset, eset;
fd_set FAR *prset =NULL, *pwset =NULL, *peset =NULL;
struct timeval tval;
int i, status, err_no =0;
time_t t1, t2;
MSG msg;
tval.tv_sec =0;
tval.tv_usec =1;
time(&t1);
t2 =t1;
while(t2-t1 < timeout)
{
FD_ZERO(&rset);
FD_ZERO(&wset);
FD_ZERO(&eset);
for(i =0; i<(int)strlen(type); i++)
{
if(type[i] =='r') { FD_SET(sd, &rset); prset =&rset; }
if(type[i] =='w') { FD_SET(sd, &wset); pwset =&wset; }
if(type[i] =='e') { FD_SET(sd, &eset); peset =&eset; }
}
status =select(-1, prset, pwset, peset, &tval);
err_no =WSAGetLastError();
int err=GetLastError();
//WriteStat("select err_no=%d, err=%d", err_no, err);
time(&t2);
if(status ==0)
{
if(PeekMessage(&msg, 0, NULL, NULL, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if(msg.message ==WM_QUIT)
{
//WSASetLastError(WSAETIMEOUT);
return -1;
}
}
if(t2-t1 else
{
if(prset) FD_CLR((UINT)sd,&rset);
if(pwset) FD_CLR((UINT)sd,&wset);
if(peset) FD_CLR((UINT)sd,&eset);
WSASetLastError(WSAEWOULDBLOCK);
return -10;
}
}
if(peset && FD_ISSET(sd, peset))
{
if(prset !=NULL) FD_CLR((UINT)sd,&rset);
if(pwset !=NULL) FD_CLR((UINT)sd,&wset);
if(peset !=NULL) FD_CLR((UINT)sd,&eset);
//err_no =WSAGetLastError();
/*
len =sizeof(errno);
getsockopt(sd, SOL_SOCKET, SO_ERROR, (char *)&errno, &len);
*/
WSASetLastError(err_no);
return -1;
}
if((prset && FD_ISSET(sd, prset)) || (pwset && FD_ISSET(sd, pwset)))
{
//err_no =WSAGetLastError();
/*
len =sizeof(errno);
getsockopt(sd, SOL_SOCKET, SO_ERROR, (char *)&errno, &len);
*/
}
if(prset !=NULL) FD_CLR((UINT)sd,&rset);
if(pwset !=NULL) FD_CLR((UINT)sd,&wset);
if(peset !=NULL) FD_CLR((UINT)sd,&eset);
//if(status <0)
//err_no =WSAGetLastError();
WSASetLastError(err_no);
if(err_no ==WSAEINTR)
{
return WSAEINTR;
}
if(err_no)
{
return -1;
}
else break;
}
return 0;
}
int CTcp::bind(HWND hWnd, int port)
{
struct sockaddr_in addr;
char temp[200];
int sd;
sd =-1;
if((sd =socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) <0)
{
sprintf(temp, "socket failed! errno:%d", WSAGetLastError());
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sin_family =AF_INET;
addr.sin_port =htons((unsigned short)port);
int l =1;
setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&l, sizeof(l));
/*setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, (char *)&l, sizeof(l));*/
if(::bind(sd, (struct sockaddr *)&addr, sizeof(addr)) <0)
{
sprintf(temp, "bind failed! errno:%d", WSAGetLastError());
closesocket(sd);
return -1;
}
if(hWnd && WSAAsyncSelect(sd, hWnd, WM_TCP, FD_ACCEPT) !=0)
{
sprintf(temp, "tcp_bind:WSAAsyncSelect failed!");
closesocket(sd);
return -2;
}
//sd_bind =sd;
listen(sd, 5);
return sd;
}
int CTcp::bind2(HWND hWnd, char *ip, int port)
{
struct sockaddr_in addr;
char temp[200];
int sd;
sd =-1;
if((sd =socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) <0)
{
sprintf(temp, "socket failed! errno:%d", WSAGetLastError());
return -1;
}
if(ip && *ip)
{
memset(&addr, 0, sizeof(addr));
ULONG ul =inet_addr(ip);
if(ul ==0xffffffff)
{
closesocket(sd);
return -1;
}
else addr.sin_addr.s_addr=ul;
}
memset(&addr, 0, sizeof(addr));
addr.sin_family =AF_INET;
addr.sin_port =htons((unsigned short)port);
int l =1;
setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&l, sizeof(l));
/*setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, (char *)&l, sizeof(l));*/
if(::bind(sd, (struct sockaddr *)&addr, sizeof(addr)) <0)
{
sprintf(temp, "bind failed! errno:%d", WSAGetLastError());
closesocket(sd);
return -1;
}
if(hWnd && WSAAsyncSelect(sd, hWnd, WM_TCP, FD_ACCEPT) !=0)
{
sprintf(temp, "tcp_bind:WSAAsyncSelect failed!");
closesocket(sd);
return -2;
}
//sd_bind =sd;
listen(sd, 5);
return sd;
}
int CTcp::accept(int sd, int timeout)
{
int sd_acc =-1;
struct sockaddr_in sa;
int len;
/*unsigned long l;*/
if(status(sd, "rw", timeout) <0)
return -1;
len =sizeof(sa);
if((sd_acc =::accept(sd, (struct sockaddr *)&sa, &len)) <0)
return -1;
//sd_accept =sd_acc;
/* l =1;
if(ioctlsocket(sd_acc, FIONBIO, &l) <0)
{
closesocket(sd);
return -1;
}*/
return sd_acc;
}
int CTcp::connect(char *hostname, int port, int timeout, int f_noblock)
{
struct hostent *hp;
struct sockaddr_in addr;
char temp[200];
unsigned long ul;
long l;
int sd =-1, ret;
time_t t1, t2;
sd =-1;
if((sd =::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) <0)
{
sprintf(temp, "socket failed! errno:%d", WSAGetLastError());
return -1;
}
memset(&addr, 0, sizeof(addr));
ul =inet_addr(hostname);
if(ul ==0xffffffff)
{
if((hp =gethostbyname(hostname)) ==NULL)
{
sprintf(temp, "gethostbyname and inet_addr failed! errno:%d", WSAGetLastError());
closesocket(sd);
return -1;
}
memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
}
else addr.sin_addr.s_addr=ul;
addr.sin_family =AF_INET;
addr.sin_port =htons((unsigned short)port);
l =1;
if(/*f_noblock && */ioctlsocket(sd, FIONBIO, (unsigned long *)&l) <0)
{
closesocket(sd);
return -1;
}
/*if(setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, (char *)&l, sizeof(l)) <0)
{
closesocket(sd);
return -1;
}*/
time(&t1);
int counter=0;
while((ret =::connect(sd, (struct sockaddr *)&addr, sizeof(addr))) !=0)
{
time(&t2);
if((t2 -t1) > timeout)
{
closesocket(sd);
return -1;
}
peek_message();
int err_no =WSAGetLastError();
if(ret ==SOCKET_ERROR)
{
if(counter++>10)
{
Sleep(100);
counter=0;
}
if(err_no ==WSAEISCONN) break;
}
else if(err_no ==WSAEWOULDBLOCK /*|| err_no ==WSAEINPROGRESS*/ || err_no ==WSAEALREADY)
{
continue;
}
else
{
closesocket(sd);
return -1;
}
}
if(status(sd, "we", timeout) <0)
{
sprintf(temp, "status:Á¬½Ó·þÎñÆ÷ʧ°Ü!\n¼ì²é·þÎñÆ÷¶Ë³ÌÐòÊÇ·ñÔËÐÐ\nÇÒÖ÷»úµØÖ·ÊÇ·ñ%s, ¶Ë¿ÚÊÇ·ñ%d\n"
"errno=%d",
hostname, port, WSAGetLastError());
closesocket(sd);
return -1;
}
//sd_connect =sd;
return sd;
}
int CTcp::connect2(char *bind_ip, char *hostname, int port, int timeout, int f_noblock)
{
struct hostent *hp;
struct sockaddr_in addr;
char temp[200];
unsigned long ul;
long l;
int sd =-1, ret;
time_t t1, t2;
sd =-1;
if((sd =socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) <0)
{
sprintf(temp, "socket failed! errno:%d", WSAGetLastError());
return -1;
}
if(bind_ip && *bind_ip)
{
memset(&addr, 0, sizeof(addr));
addr.sin_family =AF_INET;
ul =inet_addr(bind_ip);
if(ul ==0xffffffff)
{
closesocket(sd);
return -1;
}
else addr.sin_addr.s_addr=ul;
if(::bind(sd, (struct sockaddr *)&addr, sizeof(addr)) <0)
{
sprintf(temp, "tcp_connect: bind failed! errno:%d", WSAGetLastError());
closesocket(sd);
return -1;
}
}
memset(&addr, 0, sizeof(addr));
ul =inet_addr(hostname);
if(ul ==0xffffffff)
{
if((hp =gethostbyname(hostname)) ==NULL)
{
sprintf(temp, "gethostbyname and inet_addr failed! errno:%d", WSAGetLastError());
closesocket(sd);
return -1;
}
memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
}
else addr.sin_addr.s_addr=ul;
addr.sin_family =AF_INET;
addr.sin_port =htons((unsigned short)port);
l =1;
if(/*f_noblock && */ioctlsocket(sd, FIONBIO, (unsigned long *)&l) <0)
{
closesocket(sd);
return -1;
}
/*if(setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, (char *)&l, sizeof(l)) <0)
{
closesocket(sd);
return -1;
}*/
time(&t1);
int counter=0;
while((ret =::connect(sd, (struct sockaddr *)&addr, sizeof(addr))) !=0)
{
time(&t2);
if((t2 -t1) > timeout)
{
closesocket(sd);
return -1;
}
peek_message();
int err_no =WSAGetLastError();
if(ret ==SOCKET_ERROR)
{
if(counter++>10)
{
Sleep(100);
counter=0;
}
if(err_no ==WSAEISCONN) break;
}
else if(err_no ==WSAEWOULDBLOCK /*|| err_no ==WSAEINPROGRESS*/ || err_no ==WSAEALREADY)
{
continue;
}
else
{
closesocket(sd);
return -1;
}
}
if(status(sd, "we", timeout) <0)
{
sprintf(temp, "status:Á¬½Ó·þÎñÆ÷ʧ°Ü!\n¼ì²é·þÎñÆ÷¶Ë³ÌÐòÊÇ·ñÔËÐÐ\nÇÒÖ÷»úµØÖ·ÊÇ·ñ%s, ¶Ë¿ÚÊÇ·ñ%d\n"
"errno=%d",
hostname, port, WSAGetLastError());
closesocket(sd);
return -1;
}
//sd_connect =sd;
return sd;
}
void CTcp::disconnect(int sd)
{
if(sd >0)
{
closesocket(sd);
//if(sd ==sd_connect) sd_connect =-1;
//if(sd ==sd_accept) sd_accept =-1;
//if(sd ==sd_bind) sd_bind =-1;
}
}
int CTcp::send(int sd, char *buf, int len, int timeout)
{
int len1, len_send =0;
time_t t1, t2;
len_send =0;
time(&t1);
t2 =t1;
int counter=0;
while(len_send {
if(t2-t1 >timeout)
return len_send;
if(status(sd, "w", timeout-(t2-t1)) <0)
{
return len_send;
}
if((len1 =::send(sd, &buf[len_send], len-len_send, 0)) <=0)
{
if(len1 ==SOCKET_ERROR && GetLastError() ==WSAEWOULDBLOCK)
{
time(&t2);
if(counter++>100)
{
Sleep(100);
counter=0;
}
continue;
}
return len_send;
}
len_send +=len1;
time(&t2);
}
return len_send;
}
int CTcp::recv(int sd, char *buf, int len, int timeout)
{
int len1, len_recv;
time_t t2, t1;
len_recv =0;
time(&t1);
t2 =t1;
int err =0;
int counter=0;
while(len_recv {
if(t2 -t1 >timeout)
{
WSASetLastError(err);
return len_recv;
}
if(status(sd, "r", timeout-(t2-t1)) <0)
{
err =WSAGetLastError();
//WriteStat("tcp_status err=%d", WSAGetLastError());
WSASetLastError(err);
return len_recv;
}
if((len1 =::recv(sd, &buf[len_recv], len-len_recv, 0)) <=0)
{
err =WSAGetLastError();
//WriteStat("recv err=%d, len1=%d", err, len1);
if(timeout ==0) break;
if(len1 ==SOCKET_ERROR && err ==WSAEWOULDBLOCK)
{
time(&t2);
if(counter++>100)
{
Sleep(100);
counter=0;
}
continue;
}
WSASetLastError(err);
return len_recv;
}
len_recv +=len1;
time(&t2);
}
WSASetLastError(err);
return len_recv;
}
int CTcp::gethostnamebyip(char *ip, char *host)
{
struct hostent *hp;
struct in_addr ul;
host[0] =0;
ul.S_un.S_addr =inet_addr(ip);
if(ul.S_un.S_addr ==0xFFFFFFFF) return -1; // ip error or ip is hostname
hp =gethostbyaddr((char *)&ul, 4, AF_INET);
if(hp ==NULL) return -1; // can not get hostname
strcpy(host, hp->h_name);
return 0;
}
int CTcp::get_local_ip(char *ip)
{
struct hostent *hp;
char host[50], *p;
if(gethostname(host, sizeof(host)) <0) return -1;
hp =gethostbyname(host);
if(hp ==NULL) return -1;
p =(char *)hp->h_addr;
wsprintfA(ip, "%d.%d.%d.%d", (int)p[0]&0xFF, (int)p[1]&0xFF, (int)p[2]&0xFF, (int)p[3]&0xFF);
return 0;
}
char* CTcp::get_remote_ip(int sd, char *ip)
{
struct sockaddr_in addr_in;
int len =sizeof(addr_in);
char *p1;
if(sd <0) return NULL;
if(getpeername(sd, (struct sockaddr *)&addr_in, &len) <0)
return NULL;
p1 =(char *)&addr_in.sin_addr;
sprintf(ip, "%d.%d.%d.%d", ((int)p1[0]) &0xff, ((int)p1[1]) &0xff, (int)p1[2] &0xff, (int)p1[3]&0xff);
return ip;
}
unsigned short CTcp::htons(unsigned short s)
{
return ::htons(s);
}
unsigned short CTcp::ntohs(unsigned short s)
{
return ::ntohs(s);
}
unsigned long int CTcp::htonl(unsigned long int l)
{
return ::htonl(l);
}
unsigned long int CTcp::ntohl(unsigned long int l)
{
return ::ntohl(l);
}
float CTcp::htonf(float f)
{
unsigned char *p, p0, p1;
if(htons(1) ==1) return f;
p =(unsigned char *)&f;
p0 =p[0];
p1 =p[1];
p[0] =p[3];
p[3] =p0;
p[1] =p[2];
p[2] =p1;
return f;
}
float CTcp::ntohf(float f)
{
unsigned char *p, p0, p1;
if(ntohs(1) ==1) return f;
p =(unsigned char *)&f;
p0 =p[0];
p1 =p[1];
p[0] =p[3];
p[3] =p0;
p[1] =p[2];
p[2] =p1;
return f;
}
double CTcp::htond(double d)
{
unsigned char *p, p0, p1, p2, p3;
if(htons(1) ==1) return d;
p =(unsigned char *)&d;
p0 =p[0];
p1 =p[1];
p2 =p[2];
p3 =p[3];
p[0] =p[7];
p[7] =p0;
p[1] =p[6];
p[6] =p1;
p[2] =p[5];
p[5] =p2;
p[3] =p[4];
p[4] =p3;
return d;
}
double CTcp::ntohd(double d)
{
unsigned char *p, p0, p1, p2, p3;
if(ntohs(1) ==1) return d;
p =(unsigned char *)&d;
p0 =p[0];
p1 =p[1];
p2 =p[2];
p3 =p[3];
p[0] =p[7];
p[7] =p0;
p[1] =p[6];
p[6] =p1;
p[2] =p[5];
p[5] =p2;
p[3] =p[4];
p[4] =p3;
return d;
}
unsigned __int64 CTcp::htonh(unsigned __int64 d)
{
unsigned char *p, p0, p1, p2, p3;
if(htons(1) ==1) return d;
p =(unsigned char *)&d;
p0 =p[0];
p1 =p[1];
p2 =p[2];
p3 =p[3];
p[0] =p[7];
p[7] =p0;
p[1] =p[6];
p[6] =p1;
p[2] =p[5];
p[5] =p2;
p[3] =p[4];
p[4] =p3;
return d;
}
unsigned __int64 CTcp::ntohh(unsigned __int64 d)
{
unsigned char *p, p0, p1, p2, p3;
if(ntohs(1) ==1) return d;
p =(unsigned char *)&d;
p0 =p[0];
p1 =p[1];
p2 =p[2];
p3 =p[3];
p[0] =p[7];
p[7] =p0;
p[1] =p[6];
p[6] =p1;
p[2] =p[5];
p[5] =p2;
p[3] =p[4];
p[4] =p3;
return d;
}
void CTcp::peek_message(void)
{
MSG msg;
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
int CTcp::bind_listen(int port,sockaddr_in& addr,long &err)
{
int sock;
sock = socket(AF_INET, SOCK_STREAM, 0); // Create socket
addr.sin_family = AF_INET; // Address family Internet
addr.sin_port = htons (port); // Assign port 'port' to this socket
addr.sin_addr.s_addr = htonl (INADDR_ANY); // No destination
if (::bind (sock, (LPSOCKADDR) &addr, sizeof (addr)) == SOCKET_ERROR)
{
closesocket (sock);
err = WSAGetLastError ();
return -1;
}
if (::listen (sock, 10) == SOCKET_ERROR)
{
closesocket (sock);
err = WSAGetLastError ();
return -1;
}
return sock;
}
void CTcp::close(int &sd)
{
shutdown(sd,0);
closesocket(sd);
sd = INVALID_SOCKET;
}