setsockopt()和getsockopt()函数—-解决地址不可复用,即Address already in use
来源:互联网 发布:微信html5游戏源码 编辑:程序博客网 时间:2024/06/06 03:49
转载:http://blog.163.com/xychenbaihu@yeah/blog/static/1322296552011215111017599/
Linux所提供的socket库有一个错误(bug);此错误表现为你不能为一个套接字重新启动同一个端口号。 即:比如一个程序,在IP”192.168.1.234″和Port”12357″上创建了一个套接字。启动程序后,在recvfrom数据,我们用ctrl+z强制终止程序。 当我们重启程序时,被提示:: Address already in use //绑定时发生的错误。 产生问题的原因是:: Linux内核在一个绑定套接字的进程结束后,从不把端口标记为未用。 解决问题的方法:: 当套接字sockfd已经打开,即socket()创建套接字之后,使用setsockopt系统调用在这个sockfd上设定选项(options)。 Linux内核提供的系统调用:: #include <sys/types.h> #include <sys/socket.h> int getsockopt(int sockfd,int level,int name,char *value,int optlen); int setsockopt(int scokfd,int level,int name,char *value,int *optlen); 参数详解:: sockfd 必须是一个已经打开的sockfd,setsockopt应该在socket()之后就调用。 level 是函数使用的协议标准(protocol level),Linux使用的是套接字,套接字 的标准表示是SOL_SOCKET,其次TCP/IP协议使用的是IPPROTO_TCP, 我们并不关心这个。 name 在套接字中的说明,比如:SO_REUSEADDR,就是表示端口可以复用。 SO_BROADCAST,就表示将sockfd设置为可以进行广播的fd。 man手册中,name的取值比较多,我们比较关系的就是上面的两个。 value 我们用setsockopt设置数据的地址,getsockopt将在这个地址上得到值。 optlen 设置value时,value的大小。 举例:: 要实现端口复用(重复使用,即解决Address already use)。 /*创建套接字*/ int sockfd = socket(AF_INET,SOCK_DGRAM或这SOCK_STREAM,0); /*设定参数的值,即上面value和optlen的值*/ int opt = 1; int len = sizeof(opt); /*设置套接字属性,实现复用*/ setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,len); 举例:: 这里只举例setsockopt用来设置端口可以复用(重复使用的情况)的情况, getsockopt的并没有举例。getsockopt,主要用来获取sockfd的一些opt信息。 getsockopt的例子,以后有机会再补充。
代码举例 src.c :: 按ctrl+c强行终止后,会出现端口不可用的程序(Address already use)
#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>#include <netdb.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <error.h>#include <unistd.h>#include <netinet/in.h>#define MAX_LINE 4096int main(int argc,char *argv[]){struct sockaddr_in srvaddr;struct sockaddr_in cltaddr;int socklen=sizeof(struct sockaddr_in);int sockfd;char msgbuf[MAX_LINE];int msglen; int opt = 1;int len = sizeof(opt);srvaddr.sin_family = AF_INET;srvaddr.sin_addr.s_addr = inet_addr(“172.25.81.16”);srvaddr.sin_port = htons(12357);bzero(srvaddr.sin_zero,sizeof(srvaddr.sin_zero)); sockfd = socket(AF_INET,SOCK_DGRAM,0);if(sockfd == -1){perror(“creat socket fd fail:”);exit(1);}if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,len)==-1){perror(“setsockopt fail:”);close(sockfd);exit(1);} if(bind(sockfd,(struct sockaddr *)&srvaddr,sizeof(struct sockaddr_in))==-1){perror(“bind socket fd fail:”);close(sockfd);exit(1);} memset(msgbuf,0,MAX_LINE);msglen = recvfrom(sockfd,msgbuf,MAX_LINE,0,(struct sockaddr *)&cltaddr,&socklen);if(msglen < 0){perror(“recv data fail:”);close(sockfd);exit(1);}else{msgbuf[msglen] = ‘\0’;printf(“recv data from clt:%s\n”,msgbuf);memset(msgbuf,0,MAX_LINE);strcpy(msgbuf,”hello clt!”);sendto(sockfd,msgbuf,strlen(msgbuf),0,(struct sockaddr *)&cltaddr,socklen);close(sockfd);}return 0;}
编译成src,运行过程中,按ctrl+c,终止程序,重启时,端口可以复用(重复使用)。不会出现问题。
0 0
- setsockopt()和getsockopt()函数—-解决地址不可复用,即Address already in use
- 地址已经被使用——Address already in use
- 地址已经被使用——Address already in use
- 解决 Address already in use: JVM_Bind
- 解决Address Already in use:JVM_Bind错误
- 解决Address Already in use : JVM_Bind错误
- Address already in use: JVM_Bind的解决
- python解决address already in use
- bind函数错误:Address already in use
- Address already in use
- Address already in use
- Address already in use
- address already in use
- address already in use
- address already in use
- setsockopt函数和getsockopt函数
- getsockopt()函数和setsockopt()函数
- 关于setsockopt和getsockopt函数
- 略论研发评审的必要性
- React学习笔记
- 100天学会VR游戏开发
- HBase的Java接口基本操作:创建表插入查询删除
- Qt Designer使用简易教程
- setsockopt()和getsockopt()函数—-解决地址不可复用,即Address already in use
- UDP笔记
- 苏轼眼里看到的技术世界(一)
- poj 2398 Toy Storage
- java设计模式之创建型模式-抽象工厂模式
- 最大熵模型介绍及实现
- C语言单元测试框架Check
- 关于如何优化eclipse启动时间
- 为什么Hibernate的OneToMany用Set集合而不用list