请选择 进入手机版 | 继续访问电脑版

硬汉嵌入式论坛

 找回密码
 立即注册
查看: 4977|回复: 0
收起左侧

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

[复制链接]

747

主题

1048

回帖

3294

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3294
发表于 2015-10-21 23:08:16 | 显示全部楼层 |阅读模式
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详解》后再续!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-3-29 06:07 , Processed in 0.135708 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表