socket编程:SO_REUSEADDR例解

socket编程:SO_REUSEADDR例解 

                                            kevintz 2000-6-19 

    网友vmstat多次提出了这个问题:SO_REUSEADDR有什么用处和怎么使用。而
且很多网友在编写网络程序时也会遇到这个问题。所以特意写了这么一篇文章,
希望能够解答一些人的疑难。 
    其实这个问题在Richard Stevens的《Unix网络编程指南》卷一里有很详细的
解答(中文版P166-168页)。这里我只是写几个基本的例子来验证这个问题。 
    首先声明一个问题:当两个socket的address和port相冲突,而你又想重用地
址和端口,则旧的socket和新的socket都要已经被设置了SO_REUSEADDR特性,只
有两者之一有这个特性还是有问题的。 
    SO_REUSEADDR可以用在以下四种情况下。 
    (摘自《Unix网络编程》卷一,即UNPv1) 
    1、当有一个有相同本地地址和端口的socket1处于TIME_WAIT状态时,而你启
动的程序的socket2要占用该地址和端口,你的程序就要用到该选项。 
    2、SO_REUSEADDR允许同一port上启动同一服务器的多个实例(多个进程)。但
每个实例绑定的IP地址是不能相同的。在有多块网卡或用IP Alias技术的机器可
以测试这种情况。 
    3、SO_REUSEADDR允许单个进程绑定相同的端口到多个socket上,但每个soc
ket绑定的ip地址不同。这和2很相似,区别请看UNPv1。 
    4、SO_REUSEADDR允许完全相同的地址和端口的重复绑定。但这只用于UDP的
多播,不用于TCP。 

例子1:测试上面第一种情况。 

#include <netinet/in.h> 
#include <sys/socket.h> 
#include <time.h> 
#include <stdio.h> 
#include <string.h> 

#define MAXLINE 100 

int main(int argc, char** argv) 

   int listenfd,connfd; 
   struct sockaddr_in servaddr; 
   char buff[MAXLINE+1]; 
   time_t ticks; 
   unsigned short port; 
   int flag=1,len=sizeof(int); 

   port=10013; 
   if( (listenfd=socket(AF_INET,SOCK_STREAM,0)) == -1) 
   { 
     perror("socket"); 
     exit(1); 
   } 
   bzero(&servaddr,sizeof(servaddr)); 
   servaddr.sin_family=AF_INET; 
   servaddr.sin_addr.s_addr=htonl(INADDR_ANY); 
   servaddr.sin_port=htons(port); 
   if( setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &flag, len) == -
1) 
   { 
      perror("setsockopt"); 
      exit(1); 
   } 
   if( bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) == 
-1) 
   { 
      perror("bind"); 
      exit(1); 
   } 
   else 
      printf("bind call OK!/n"); 
   if( listen(listenfd,5) == -1) 
   { 
      perror("listen"); 
      exit(1); 
   } 
   for(;;) 
   { 
      if( (connfd=accept(listenfd,(struct sockaddr*)NULL,NULL)) == -1)

      { 
          perror("accept"); 
          exit(1); 
      } 
      if( fork() == 0)/*child process*/ 
      { 
        close(listenfd);/*这句不能少,原因请大家想想就知道了。*/ 
        ticks=time(NULL); 
        snprintf(buff,100,"%.24s/r/n",ctime(&ticks)); 
        write(connfd,buff,strlen(buff)); 
        close(connfd); 
        sleep(1); 
        execlp("f1-9d",NULL); 
        perror("execlp"); 
        exit(1); 
     } 
     close(connfd); 
     exit(0);/* end parent*/ 
  } 



测试:编译为f1-9d程序,放到一个自己PATH环境变量里的某个路径里,例如$HO
ME/bin,运行f1-9d,然后telnet localhost 10013看结果。 

2、第二种情况我没有环境测,所以就不给测试程序了,大家有条件的可以自己写
一个来测试一下。 
     
3、测试第三种情况的程序 

#include <netinet/in.h> 
#include <sys/socket.h> 
#include <time.h> 
#include <stdio.h> 
#include <string.h> 

#define MAXLINE 100 

int main(int argc, char** argv) 

   int fd1,fd2; 
   struct sockaddr_in servaddr1,servaddr2; 
   char buff[MAXLINE+1]; 
   time_t ticks; 
   unsigned short port; 
   int flag=1,len=sizeof(int); 

   port=10013; 
   if( (fd1=socket(AF_INET,SOCK_STREAM,0)) == -1) 
   { 
       perror("socket"); 
       exit(1); 
   } 
   if( (fd2=socket(AF_INET,SOCK_STREAM,0)) == -1) 
   { 
       perror("socket"); 
       exit(1); 
   } 
   bzero(&servaddr1,sizeof(servaddr1)); 
   bzero(&servaddr2,sizeof(servaddr2)); 
   servaddr1.sin_family=AF_INET; 
   servaddr2.sin_family=AF_INET; 

   if( inet_pton(AF_INET, "127.0.0.1", &servaddr1.sin_addr) <= 0) 

printf("inet_pton() call error:127.0.0.1/n"); 
exit(1); 

if( inet_pton(AF_INET, "128.160.1.230", &servaddr2.sin_addr) <= 0) 


printf("inet_pton() call error:128.160.1.230/n"); 
exit(1); 

servaddr1.sin_port=htons(port); 
servaddr2.sin_port=htons(port); 
if( setsockopt(fd1, SOL_SOCKET, SO_REUSEADDR, &flag, len) == -1) 

perror("setsockopt"); 
exit(1); 

if( setsockopt(fd2, SOL_SOCKET, SO_REUSEADDR, &flag, len) == -1) 

perror("setsockopt"); 
exit(1); 

if( bind(fd1,(struct sockaddr*)&servaddr1,sizeof(servaddr1)) == -1)


perror("bind fd1"); 
exit(1); 

if( bind(fd2,(struct sockaddr*)&servaddr2,sizeof(servaddr2)) == -1)


perror("bind fd2"); 
exit(1); 

printf("bind fd1 and fd2 OK!/n"); 
/*put other process here*/ 
getchar(); 
exit(0);/* end */ 

4、由于第四种情况只用于UDP的多播,和TCP的使用没多大关系,所以就不写测试
例子了。自己有兴趣的可以写。 

以上的程序都是在Linux下编译通过的。也可以在其他unix平台运行。 

参考资料: 
1、《Unix网络编程》卷一 R. Stevens 
2、《Socket programming FAQ》 http://www.ibrado.com/sock-faq/

时间: 2024-08-04 04:54:50

socket编程:SO_REUSEADDR例解的相关文章

Python socket编程实例详解

  本文实例形式较为详细的讲述了Python socket编程.分享给大家供大家参考.具体如下: 复制代码 代码如下: sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 上面的代码创建了一个socket对象.type参数代表套接字类型,可为SOCK_STREAM(流套接字)和SOCK_DGRAM(数据报套接字).AF_INET表示创建的是ip v4的类型. 复制代码 代码如下: socket(address_family,type,pro

PHP Socket 编程过程详解

介绍 Socket用于进程间通信.进程间通信通常基于客户端-服务端模型.此时,客户端-服务端是可以彼此交互的应用程序.客户端和服务端之间的交互需要连接.Socket编程负责的就是为应用程序之间建立可进行交互的连接. 在本文中,我们将学习如何用PHP创建一个简单的客户端-服务端.我们还将学习如何客户端应用程序如何发送消息到服务端,以及如何从服务端接受消息. 使用代码 目的:开发一个客户端用于发送string消息到服务端,服务端将相同的信息反转后返回给客户端. PHP服务器 第1步:设置变量,如"主

php的socket编程详解_php技巧

php的socket编程算是比较难以理解的东西吧,不过,我们只要理解socket几个函数之间的关系,以及它们所扮演的角色,那么理解起来应该不是很难了,在笔者看来,socket编程,其实就是建立一个网络服务的客户端和服务端,这和mysql的客户端和服务端是一样的,你只要理解mysql的客户端和服务端是怎么一回事,你就应该能够理解下面我要讲的东西吧. 关于socket编程所涉及到的网络协议,什么TCP啊,UDP啊,什么socket三次握手等等,这些网络协议网上有很详细的解释,这里不讲,只截个sock

详解Linux Socket编程(不限Linux)_Linux

我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览器浏览网页时,浏览器的进程怎么与web服务器通信的?当你用QQ聊天时,QQ进程怎么与服务器或你好友所在的QQ进程通信?这些都得靠socket?那什么是socket?socket的类型有哪些?还有socket的基本函数,这些都是本文想介绍的.本文的主要内容如下: 1.网络中进程之间如何通信? 本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类: 消息传递(管道.FIFO.消息队列) 同步(互斥量.条件变量.读写锁.文件和

PHP SOCKET编程详解

  这篇文章主要介绍了PHP SOCKET编程详解,需要的朋友可以参考下 1. 预备知识 一直以来很少看到有多少人使用php的socket模块来做一些事情,大概大家都把它定位在脚本语言的范畴内吧,但是其实php的socket模块可以做很多事情,包括做ftplist,http post提交,smtp提交,组包并进行特殊报文的交互(如smpp协议),whois查询.这些都是比较常见的查询. 特别是php的socket扩展库可以做的事情简直不会比c差多少. php的socket连接函数 1.集成于内核

PHP SOCKET编程详解_php技巧

1. 预备知识 一直以来很少看到有多少人使用php的socket模块来做一些事情,大概大家都把它定位在脚本语言的范畴内吧,但是其实php的socket模块可以做很多事情,包括做ftplist,http post提交,smtp提交,组包并进行特殊报文的交互(如smpp协议),whois查询.这些都是比较常见的查询. 特别是php的socket扩展库可以做的事情简直不会比c差多少. php的socket连接函数 1.集成于内核的socket 这个系列的函数仅仅只能做主动连接无法实现端口监听相关的功能

详解Linux的SOCKET编程_C 语言

本篇文章对Linux的SOCKET编程进行了详细解释文章后面分享了一个编程实例供大家学习. 1. 网络中进程之间如何通信 进程通信的概念最初来源于单机系统.由于每个进程都在自己的地址范围内运行为保证两个相互通信的进程之间既互不干扰又协调一致工作操作系统为进程通信提供了相应设施如 UNIX BSD有管道pipe.命名管道named pipe软中断信号signal UNIX system V有消息message.共享存储区shared memory和信号量semaphore)等. 他们都仅限于用在本

详解C# Socket编程笔记_C#教程

看到这个题目,是不是很眼熟?在博客园里搜下,保证会发现关于这个东东的文章实在是太多了~~~真得是没有写得必要,而且我也有点懒得去琢磨字句.(看到这,肯定得来个转折的了,不然就看不到下文了,不是吗)但是,为了自己下一篇要写的文章做参考,还是有必要先补充一下socket基础知识. 注意:如果你已经接触过socket,那就没什么必要耽误时间看下去了.另外,如果发现其中任何错误,欢迎直接指出. 1.按惯例先来介绍下socket Windows中的很多东西都是从Unix领域借鉴过来的,Socket也是一样

Java基于Socket实现网络编程实例详解_java

一,网络编程中两个主要的问题 一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输. 在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可以唯一地确定Internet上的一台主机. 而TCP层则提供面向应用的可靠(tcp)的或非可靠(UDP)的数据传输机制,这是网络编程的主要对象,一般不需要关心IP层是如何处理数据的. 目前较为流行的网络编程模型是客户机/服务器(C/S)结构.即通信双方一方作为服务器等待客户提出请求并予以响应.客户则