一个多socket绑定同一个端口的测试程序

 

测试目标:建立多个socket的测试

 

测试环境:suse Linux

 

测试步骤:建立了3个socket,但是由于绑定了不同的端口,可以邦定成功;假如绑定相同的端口,则相继失败。而关闭socket的时候,调用shutdown失败,而close却可以成功。

在stevens的书本中,则建议使用shutdown来关闭,但是,不成功。

 

测试结果:

goal: test multi socket could be binded in the same port
creating socket:
socket is created: 3
socket is created: 4
socket is created: 5


current pid: %d
18116


bind socket:

binding the 8000 port
binding the 8001 port
binding the 8002 port


shut down  the socket
shut down socket 1 error
shut down socket 2 error
shut down socket 333 error

疑问:

1、为什么一个程序不同的socket不可以邦定同一个端口呢?

2、为什么shutdown失败?而close则可以成功呢?

3、为什么多个进程里面,每个进程都有一个socket,多个进程绑定的却是同一个端口,还是失败呢?

 

测试源代码:

 

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. #include <sys/time.h>
  5. #include <sys/types.h>
  6. #include <string.h>
  7. #include <signal.h>
  8. #include <sys/socket.h>
  9. #include <netinet/in.h>
  10. #include <arpa/inet.h>
  11. #include <errno.h>
  12. #include <unistd.h>
  13. #include <iostream>
  14. using namespace std;
  15. int bind_socket(int sock, int port);
  16. int create_socket();
  17. int main(int argc, char** argv)
  18. {
  19.     std::cout << "goal: test multi socket could be binded in the same port" << endl;
  20.     
  21.     int socket_1, socket_2, socket_3;
  22.     int port_1 = 8000, port_2 = 8001, port_3 = 8002;
  23.     std::cout << "creating socket:" << endl;    
  24.     socket_1 = create_socket();
  25.     std::cout << "socket is created: " << socket_1 << endl;
  26.     
  27.     socket_2 = create_socket();
  28.     std::cout << "socket is created: " << socket_2 << endl;
  29.          
  30.     socket_3 = create_socket();
  31.     std::cout << "socket is created: " << socket_3 << endl;
  32.     std::cout << "/n/ncurrent pid: " << getpid() << endl;
  33.     std::cout << "/n/nbind socket:/n" << endl;
  34.     std::cout << "binding the " << port_1 << " port" << endl;
  35.     if(bind_socket(socket_1, port_1) == -1 )
  36.     {
  37.         std::cout << "bind socket 1 error" << endl;    
  38.     }
  39.     
  40.     std::cout << "binding the " << port_2 << " port" << endl;
  41.     if(bind_socket(socket_2, port_2) == -1 )
  42.     {
  43.         std::cout << "bind socket 2 error" << endl;    
  44.     }
  45.     
  46.     std::cout << "binding the " << port_3 << " port" << endl;
  47.     if(bind_socket(socket_3, port_3) == -1 )
  48.     {
  49.         std::cout << "bind socket 3 error" << endl; 
  50.     }
  51.     std::cout << "/n/nshut down  the socket" << endl;
  52.     if(shutdown(socket_1, SHUT_RDWR) == -1)
  53.     {
  54.         std::cout << "shut down socket 1 error" << endl;
  55.      if(close(socket_1) == -1)
  56.          std::cout << "close socket 1 failed" << endl;
  57.     }
  58.     
  59.     if(shutdown(socket_2, SHUT_RDWR) == -1)
  60.     {
  61.         std::cout << "shut down socket 2 error" << endl;
  62.     }
  63.     
  64.     if(shutdown(socket_3, SHUT_RDWR) == -1)
  65.     {
  66.         std::cout << "shut down socket 333 error" << endl;
  67.     }
  68.     return 1; 
  69. }
  70. int create_socket()
  71. {
  72.     int s;
  73.     
  74.     if((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  75.     {
  76.         std::cout << "create socket failed!" << endl;
  77.         close(s);
  78.         return -1;
  79.     }
  80.     
  81.     return s;
  82. }
  83. int bind_socket(int sock, int port)
  84. {
  85.     struct sockaddr_in addr;
  86.     if(sock <= 0)
  87.     {
  88.         std::cout << "input socket error: " << sock << endl;    
  89.         return -1;
  90.     }
  91.     
  92.     if(port <= 1024)
  93.     {
  94.         std::cout << "intput port error: " << port << endl;
  95.         return -1;    
  96.     }
  97.     
  98.     memset(&addr, 0, sizeof(addr));
  99.     addr.sin_port = htons (port);
  100.     addr.sin_family = AF_INET;
  101.     
  102.     int ret = bind(sock,(struct sockaddr *)&addr, sizeof(addr));
  103.     if( ret < 0) 
  104.     {
  105.         std::cout << "bind error: " << ret << endl;
  106.         close(sock);
  107.      std::cout << "close socket: " << sock << endl;
  108.         return -1;
  109.     }
  110.     
  111.     return ret;   
  112. }

结果分析:

问题1:同事告诉我可以的,结果证明不行。说明Ericsson的TSP的强大性,哈哈

问题2:看来就用close吧。在TSP封装后的接口中,使用的是close而不是shutdown,在通用程序中,也是使用close居多。而两者的最大区别就是socket descriptor dup之后的差别,也就是说,不把socket descriptor dup的话,两者效果一样。

问题3:我使用的测试程序是:启动程序,然后fork两个进程,每个都建立一个socket,这样3个socket都绑定到了同一个端口,结果失败。因此,并不是每个进程都可以侦听同一个端口的。这样一说,也不难理解啦。

 

欢迎拍砖!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Netty是一个异步事件驱动的网络框架,可以通过使用不同的传输协议(如TCP、UDP等)来实现网络通信。Socket是一种基于TCP/IP协议的通信方式,它提供了一种可靠的面向连接的数据传输方式。而WebSocket是一种在单个TCP连接上全双工通信的协议。 在Netty中,可以通过组合的方式来支持使用不同的传输协议和通信方式,包括Socket和WebSocket。当需要在同一个端口上同时支持Socket和WebSocket时,可以通过将相关的ChannelHandler添加到Netty的ChannelPipeline中来实现。 首先,需要创建一个Netty的ServerBootstrap对象,并设置相关的配置参数,如监听端口号等。接下来,可以使用Netty提供的各种ChannelHandler来处理Socket和WebSocket请求。 对于Socket请求,可以使用Netty的SocketChannel和对应的ChannelHandler来处理。通过创建一个自定义的ChannelInitializer,并重写其中的initChannel方法,将SocketChannel和对应的SocketChannelHandler添加到ChannelPipeline中。 对于WebSocket请求,可以使用Netty提供的WebSocketServerProtocolHandler来处理。该Handler可以解析WebSocket握手请求,并将请求升级为WebSocket连接。可以将WebSocketServerProtocolHandler添加到ChannelPipeline的最前面。 通过上述步骤配置好Netty的ServerBootstrap对象后,可以开始监听和接收来自客户端的Socket和WebSocket请求。当有新的连接建立时,Netty会自动调用对应的ChannelHandler来处理请求,包括解析和处理数据。 总的来说,Netty提供了强大的可扩展性和灵活性,可以通过组合不同的ChannelHandler来实现在同一个端口上同时支持Socket和WebSocket通信。这使得开发者可以根据实际需求选择不同的通信方式,并简化了服务器的管理和维护。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值