TCP协议属性设置之SO_REUSEADDR属性

此属性用于设置某个端口是否允许重用。这个属性的用处在那里呢?当我们编写程序时监听了一个端口,但是由于某种情况,服务器程序关闭或者一场退出。造成本地端口出现TIME_WAIT状态时。这是当我们继续监听此端口时就会出现错误。这是设置这个属性就显得非常重要。当我们设置了这个属性以后就可以继续对此端口进行监听。
但是这就引出了另外的一个问题,就是设置这个属性后允许一个套接字上同时有两个应用程序进行监听,那系统究竟会将数据发送给哪一个程序呢?系统会将数据首先交给监听IP最确定的应用程序。例如应用程序A在调用监听函数时设置的属性是addr.sin_addr.S_addr := INADDR_ANY;而另外的一个应用程序B则监听的地址为addr.sin_addr.S_addr := inet_addr(PChar(sMainIP));同时这两个应用程序监听的端口都是相同的,这是系统接收到数据后会首先交给B然后再交给A。因此一般为了程序安全我们会禁止这种情况的发生。因此需要设置下面的SO_EXCLUSIVEADDRUSE属性。
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
翻译这段代码并在每一行后进行注释int ret,listen_fd, client_fd; struct sockaddr_in server_addr, client_addr; socklen_t slen, clen = sizeof(client_addr); char recvBuffer[128] = {0}; char recCmd[128] = {0}; const int on = 1; listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(listen_fd < 0) { printf("server socket failed\n"); exit(1); } server_addr.sin_family = AF_INET; server_addr.sin_port = htons(SERVERPT); server_addr.sin_addr.s_addr = htons(INADDR_ANY); slen = sizeof(server_addr); //绑定网络设备 setsockopt(listen_fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); ret = bind(listen_fd, (struct sockaddr *)&server_addr, slen); if(ret < 0) { printf("listen_fd bind failed\n"); exit(1); } ret = listen(listen_fd, 8); if(ret < 0) { printf("server listen failed\n"); exit(2); } //开始侦听客户端的连接请求 printf("Waiting connect.....\n"); client_fd = accept(listen_fd, (struct sockaddr *)&client_addr, (socklen_t *)&clen); if(client_fd < 0) { printf("server accept failed\n"); exit(3); } //连接成功,打印客户端的网卡信息 printf("client port: %d ,", ntohs(client_addr.sin_port)); printf("client ip: %s\n",inet_ntoa(client_addr.sin_addr)); while(1) { printf("Waiting recv.....\n"); ret = read(client_fd, recvBuffer, 128); if(ret < 0) printf("read failed\n"); else if(ret == 0) { //客户端下线 close(client_fd); break; } else { //打印接收到客户端信息 printf("client data: %s\n", recvBuffer); //给客户端回发信息 write(client_fd, "Successfully received your message!", 128); } }
最新发布
06-01
/* 定义三个变量:ret, listen_fd, client_fd */ int ret, listen_fd, client_fd; /* 定义两个结构体变量:server_addr, client_addr */ struct sockaddr_in server_addr, client_addr; /* 定义两个变量:slen, clen,slen记录server_addr的大小,clen记录client_addr的大小 */ socklen_t slen, clen = sizeof(client_addr); /* 定义两个字符数组:recvBuffer、recCmd,长度都为128,初始化为0 */ char recvBuffer[128] = {0}; char recCmd[128] = {0}; /* 定义一个常量on为1,表示开启相关选项 */ const int on = 1; /* 创建一个TCP协议的套接字,返回一个文件描述符 */ listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); /* 如果listen_fd小于0,表示创建套接字失败,输出提示信息并结束程序 */ if(listen_fd < 0) { printf("server socket failed\n"); exit(1); } /* 设置server_addr结构体的属性 */ server_addr.sin_family = AF_INET; //地址族为IPv4 server_addr.sin_port = htons(SERVERPT); //端口号,需要用htons转换为网络字节序 server_addr.sin_addr.s_addr = htons(INADDR_ANY); //IP地址,使用INADDR_ANY表示本机任意IP地址 slen = sizeof(server_addr); //记录server_addr结构体的大小 /* 设置socket选项,允许地址重用 */ setsockopt(listen_fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); /* 绑定网络设备和端口,将socket与server_addr绑定 */ ret = bind(listen_fd, (struct sockaddr *)&server_addr, slen); /* 如果绑定失败,输出提示信息并结束程序 */ if(ret < 0) { printf("listen_fd bind failed\n"); exit(1); } /* 开始侦听客户端的连接请求,最多连接8个客户端 */ ret = listen(listen_fd, 8); /* 如果侦听失败,输出提示信息并结束程序 */ if(ret < 0) { printf("server listen failed\n"); exit(2); } /* 输出等待客户端连接的提示信息 */ printf("Waiting connect.....\n"); /* 接受客户端连接请求,返回一个文件描述符 */ client_fd = accept(listen_fd, (struct sockaddr *)&client_addr, (socklen_t *)&clen); /* 如果接受请求失败,输出提示信息并结束程序 */ if(client_fd < 0) { printf("server accept failed\n"); exit(3); } /* 连接成功,打印客户端的网卡信息 */ printf("client port: %d ,", ntohs(client_addr.sin_port)); printf("client ip: %s\n",inet_ntoa(client_addr.sin_addr)); /* 进入循环,不断接收客户端发送的消息并回复 */ while(1) { /* 输出等待接收数据的提示信息 */ printf("Waiting recv.....\n"); /* 读取客户端发送的数据,返回读取到的字节数 */ ret = read(client_fd, recvBuffer, 128); /* 如果读取失败,输出提示信息 */ if(ret < 0) printf("read failed\n"); /* 如果读取到的字节数为0,表示客户端已下线,关闭连接并跳出循环 */ else if(ret == 0) { close(client_fd); break; } /* 如果读取到了数据,打印接收到的消息,并回复客户端 */ else { printf("client data: %s\n", recvBuffer); write(client_fd, "Successfully received your message!", 128); } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值