关于socket bind的理解

简介: socket bind的ip和port的选择

使用bind函数绑定ip和端口时有如下几种可能:

ip地址 端口 结果
通配地址 0 内核选择ip地址和端口
通配地址 非0 内核选择ip地址,进程指定端口
本地ip地址 0 进程指定ip地址,内核选择端口
本地ip地址 非0 进程指定ip地址和端口

使用规则:

  1. 服务器进程一般在启动时都会bind某个端口(例如 http的80端口),而客户端进程都不会指定端口。若未调用bind接口,则内核会为其指定一个临时端口。

服务端进程也有不指定端口的case,比如rpc服务。服务端进程在listen后向 rpc服务注册进程 注册自己的地址和端口。rpc客户端只需要向 rpc服务注册进程 请求对应的服务,即可返回rpc服务的ip和port信息。

  1. 若指定ip地址,则该ip地址必须是属于其主机的网络接口之一(127.0.0.1,网卡eth0地址 192.168.0.102,其他网卡地址)。

对于tcp客户端来说,其指定发送ip数据报的源地址
对于tcp服务端来说,其限定了该socket只接收目的地址为该ip的connect请求。

若tcp服务端不指定ip,内核会把客户端发送的syn的目的地址作为服务端的源地址(该connect socket的源地址)
注:一个listen socket可以accept多个socket连接,accept返回的connect socket的源地址可能为127.0.0.1192.168.0.102,或者其他本机ip

下面用代码证实下:
一般,启动服务器监听的代码如下:

    // 服务端代码
    int listenfd, connfd;
    struct sockaddr_in server_addr;
    listenfd = Socket(AF_INET, SOCK_STREAM, 0);

    bzero(&server_addr, sizeof(server_addr));
    // 必须是网络序
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(1234);
// 指定ip
//    char *host = "127.0.0.1";
//    inet_pton(AF_INET, host, &server_addr.sin_addr);
    Bind(listenfd, (SA*)&server_addr, sizeof(server_addr));
    Listen(listenfd, LISTENQ);

    while (1) {
        len = sizeof(cli_addr);
        connfd = Accept(listenfd, (SA*)&cli_addr, &len);
        printf("connect from %s, port:%d\n",
               inet_ntop(AF_INET, &cli_addr.sin_addr, buffer, sizeof(buffer)),
               ntohs(cli_addr.sin_port));

     struct sockaddr_in peer_addr, local_addr;
    // 获取connect fd 的本机ip和port
        int err = getsockname(connfd, (SA *)&local_addr, &len);
        
        if (err >=0 ) {
            printf("sock name %s, port:%d\n",
                   inet_ntop(AF_INET, &local_addr.sin_addr, buffer, sizeof(buffer)), ntohs(local_addr.sin_port));
        }
    // 获取客户端的本机ip和port
        err = getpeername(connfd, (SA*) &peer_addr, &len);

        if (err >=0 ) {
            printf("peer sock name %s, port:%d\n",
                   inet_ntop(AF_INET, &peer_addr.sin_addr, buffer, sizeof(buffer)), ntohs(peer_addr.sin_port));
        }
     }

服务端程序绑定在通配ip

  1. 启动绑定在通配ip和1234端口的服务端程序
  2. 使用 telnet 127.0.0.1 1234命令连接服务端
  3. 服务端显示

connect from 127.0.0.1, port:58271
sock name 127.0.0.1, port:1234

peer sock name 127.0.0.1, port:58271

  1. 使用 telnet 192.168.0.102 1234 连接服务端
  2. 服务端显示

connect from 192.168.0.102, port:58282
sock name 192.168.0.102, port:1234

peer sock name 192.168.0.102, port:58282

服务端程序绑定在 127.0.0.1

  1. 反注释以下代码,启动服务端程序
//    char *host = "127.0.0.1";
//    inet_pton(AF_INET, host, &server_addr.sin_addr);
  1. 使用 telnet 127.0.0.1 1234命令连接服务端
  2. 服务端显示

connect from 127.0.0.1, port:58271
sock name 127.0.0.1, port:1234

peer sock name 127.0.0.1, port:58271

  1. 使用 telnet 192.168.0.102 1234 连接服务端
  2. 客户端显示

telnet: connect to address 192.168.0.102: Connection refused
telnet: Unable to connect to remote host

注:telnet 操作相当于connect指定了服务端的ip和port

目录
相关文章
|
6月前
|
网络协议 Unix Linux
计算机网络 套接字函数 | socket、bind、listen、accept、connect
计算机网络 套接字函数 | socket、bind、listen、accept、connect
58 0
|
20天前
|
消息中间件 Kafka
org.apache.kafka.common.KafkaException: Socket server failed to bind to 114.115.20.100:9092: Cannot
org.apache.kafka.common.KafkaException: Socket server failed to bind to 114.115.20.100:9092: Cannot
8 0
|
10月前
|
网络安全
socket服务部署到服务端后启动失败Cannot assign requested address: bind 的总结
socket服务部署到服务端后启动失败Cannot assign requested address: bind 的总结
181 0
|
网络协议 NoSQL Redis
Could not create server TCP listening socket 127.0.0.16379 bind 操作成功
Could not create server TCP listening socket 127.0.0.16379 bind 操作成功
Could not create server TCP listening socket 127.0.0.16379 bind 操作成功
|
网络协议 NoSQL Redis
Start_Redis Nov 21:11:04.422 # Creating Server TCP listening socket 127.0.0.1:6379: bind: No error
启动 redis-server.exe 报错19 Nov 21:11:04.422 # Creating Server TCP listening socket 127.0.0.1:6379: bind: No error
409 0
|
监控 网络协议 Unix
Socket的基本操作函数socket()、bind()、listen()、connect()、accept()、recv()、send()、select()、close()
Socket的基本操作函数socket()、bind()、listen()、connect()、accept()、recv()、send()、select()、close()
674 0
Socket的基本操作函数socket()、bind()、listen()、connect()、accept()、recv()、send()、select()、close()
|
应用服务中间件
【tomcat】启动报错:Failed to initialize end point associated with ProtocolHandler ["http-apr-8080"] java.lang.Exception: Socket bind failed 和java.net.BindE
背景:【新手】 将开发机子上的Tomcat连同其中的项目,一起拷贝到服务器上,启动tomcat的start.bat,然后报错如下: 问题1: Failed to initialize end point associated with ProtocolHandler ["http-apr-8080"] java.
3703 0
|
网络协议 NoSQL Redis
启动redis出现Creating Server TCP listening socket *:6379: bind: No such file or directory
E:\redis>redis-server.exe redis.windows.conf [8564] 10 Oct 20:00:36.745 # Creating Server TCP listening socket *:6379: bind: No such file or directory E:\redis>   [6644] 02 Apr 23:11:58.
2599 0
|
网络协议 Linux API
Linux TCP/IP协议栈之Socket的实现分析(socket bind)
当创建了一个Socket 套接字后,对于服务器来说,接下来的工作,就是调用 bind(2)为服务器指明本地址、协议端口号,常常可以看到这样的代码:strut sockaddr_in sin;  sin.
867 0