armfly 发表于 2015-10-21 23:08:16

关于TCP客户端绑定固定端口的问题

http://m.blog.csdn.net/blog/wlnlgt/8973296
http://ctc.qzs.qq.com/ac/b.gif
      去年写的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详解》后再续!
页: [1]
查看完整版本: 关于TCP客户端绑定固定端口的问题