|
http://m.blog.csdn.net/blog/wlnlgt/8973296
去年写的TCP网络小程序,因为某种原因必须固定Client端的端口。于是就直接bind(下文红色字体为添加的bind,去掉即为我们常见的普通Client创建)解决!代码如下:
int CreateTcpSocketClient(const char *szip,const short iPort)
{
SOCKET fd;
fd=socket(AF_INET,SOCK_STREAM,0); if(fd==INVALID_SOCKET)
return -1;
struct sockaddr_in client_addr; memset(&client_addr,0,sizeof(client_addr)); client_addr.sin_family=AF_INET;
client_addr.sin_addr.s_addr=INADDR_ANY; client_addr.sin_port=htons(8000);//假设绑定本地8000端口
if(bind(fd,(SOCKADDR *)& client_addr,sizeof(client_addr))==SOCKET_ERROR)
return -1;
struct sockaddr_in addr;
memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_port=htons(iPort);
addr.sin_addr.s_addr=inet_addr(szip);
int iRet=connect(fd,(SOCKADDR *)&addr,sizeof(addr));
if(iRet==SOCKET_ERROR)
{
int iError=WSAGetLastError();
return -1;
}
return fd;
}
OK!解决!相安无事!
没多久发现新问题:程序没法重连。当时猜测必定是上次bind的端口没有释放导致本次bind失败。因为有其他事情要做,所以这个错误没有一直查下去。反正程序能跑一周,手动重连将就着用吧,干脆多开了几个端口,这个不行换那个(哈哈,太懒啊)。
一年过去了,这个问题几乎被忘的一干二净。最近某个客户又需要这个程序,然后就轻车熟路给他弄好。某天接到客户电话,劈头盖脸一顿臭骂!赶紧看,昨天凌晨断了。事态严重啊。
GetLastError()获取10048错误。查阅资料。原来closesocket进行关闭操作后,虽然closesocket执行完毕,但是对应的占用端口并不是立即释放,这些端口需要继续处于某种状态,等待时间大约2ML(数据包最大生存周期),默认最大值为4分钟。用netstat命令查看端口状态,端口显示TIME_WAIT,在4分钟内如果对同一个端口进行connect,就会发生10048错误。bind第二次执行时它本身并不返回错误,但是在紧接着调用connect()时会出错,错误码就是10048。解决办法:设置SO_LINGER。又OK!如下
int CreateTcpSocketClient(const char *szip,const short iPort){
SOCKET fd;
fd=socket(AF_INET,SOCK_STREAM,0); if(fd==INVALID_SOCKET)
return -1;
struct sockaddr_in client_addr; memset(&client_addr,0,sizeof(client_addr)); client_addr.sin_family=AF_INET;
client_addr.sin_addr.s_addr=INADDR_ANY; client_addr.sin_port=htons(8000);//假设绑定本地8000端口
linger optval;
optval.l_linger=0;
optval.l_onoff=1;
setsockopt(fd,SOL_SOCKET,SOL_LINGER,(const char *)&optval,sizeof(optval); if(bind(fd,(SOCKADDR *)& client_addr,sizeof(client_addr))==SOCKET_ERROR)
return -1;
struct sockaddr_in addr; memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET; addr.sin_port=htons(iPort);
addr.sin_addr.s_addr=inet_addr(szip);
int iRet=connect(fd,(SOCKADDR *)&addr,sizeof(addr));
if(iRet==SOCKET_ERROR)
{
int iError=WSAGetLastError(); return -1;
}
return fd;}
至于其他相关问题,待我看完《TCT/IP详解》后再续! |
|