sockfd
是套接字(socket)类型,是文件描述符
1. sockfd 绑定的端口是谁的端口?
sockfd
是服务器创建的一个套接字描述符,它通过 bind()
函数绑定到一个特定的 IP 地址和端口号上。
-
端口的概念:端口是一个标识特定应用程序或服务的数字。服务器程序绑定到一个端口上,以便客户端知道如何连接它。
-
当服务器通过
sockfd
调用bind()
绑定端口时,这个端口就是服务器的端口,它用于监听客户端的连接请求。客户端知道服务器的 IP 地址和端口号后,就可以向该端口发起连接。
所以,sockfd
绑定的是服务器的端口号,是服务器通过该端口接收客户端请求的入口。
2. sockfd如何监听,如何构建新连接?
当服务器使用 listen()
函数监听连接请求后,客户端会通过 connect()
函数向服务器发出请求。
-
新连接指的是服务器接收到客户端的请求后,通过
accept()
函数创建一个新的套接字描述符。这个新的描述符专门用于处理与该特定客户端的通信。 -
过程概述:
-
监听连接:服务器使用
listen()
监听来自客户端的连接请求。此时,sockfd
仍然只是监听套接字,用于等待连接请求。 -
建立新连接:当有客户端请求连接时,
accept()
会被调用,创建一个新的套接字(通常称为clientfd
),用于与这个特定客户端通信。 -
多客户端连接:服务器可以同时处理多个客户端的请求。每个客户端连接请求都会生成一个新的套接字,用于处理与该客户端的通信。clientfd包含客户端的ip地址和端口号来区分
-
一个贴切的比喻
sockfd 像是迎宾员:负责站在门口(监听套接字,绑定了服务器的端口),等待客人(客户端)来请求服务。
客户端连接:当客人(客户端)到达并提出需求时,迎宾员(sockfd
)会把客人带到一个特定的服务员(clientfd
),这个服务员专门处理该客人的需求(新连接)。
新连接的含义:每个客人(客户端)都会有自己的服务员(新的套接字 clientfd
),他们之间可以单独交流,而迎宾员继续等待其他新客人。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
int main() {
int sockfd;
struct sockaddr_in server_addr; //配置服务器
// 创建套接字
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
// 配置服务器地址结构
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY; // 接受任意地址的连接
server_addr.sin_port = htons(8080); // 绑定端口 8080
// 绑定套接字到端口
if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("bind failed");
close(sockfd);
exit(EXIT_FAILURE);
}
// 设置套接字为监听状态,最多接受 10 个待处理连接
if (listen(sockfd, 10) < 0) {
perror("listen failed");
close(sockfd);
exit(EXIT_FAILURE);
}
printf("Server is listening on port 8080...\n");
// 后续代码用于接受连接和处理客户端请求
// ...
// 关闭套接字
close(sockfd);
return 0;
}
以下是我个人的一些问题,搜寻答案如下:
1. clientfd
和 sockfd
是否都是 socket 类型?
是的,clientfd
和 sockfd
都是套接字(socket)类型,它们都是文件描述符,都是通过 socket()
函数创建的。
-
sockfd
是服务器最初创建的套接字,用于监听客户端连接请求。 -
clientfd
是通过accept()
函数为每个客户端创建的新的套接字,用于与该特定客户端进行通信。
虽然它们都是套接字,但它们的用途不同:
-
sockfd
负责监听连接。 -
clientfd
负责与客户端的具体数据交互。
2. clientfd
的端口与 sockfd
是否相同?
clientfd
和 sockfd
端口相同,但它们的使用方式不同。
-
服务器的
sockfd
绑定的端口是服务器端的端口,例如 80(HTTP)或 8080(自定义服务端口),它通过这个端口监听客户端连接。 -
当
accept()
被调用时,clientfd
会创建用于与客户端通信的套接字。此时,clientfd
仍然使用服务器的同一个端口,但同时它也记录了客户端的 IP 地址和客户端的临时端口号(由客户端动态分配),用于与该客户端的后续通信。
3. 客户端请求新连接也是通过客户端的端口吗?
是的,客户端通过它自己的端口发起连接请求。具体来说:
-
当客户端使用
socket()
创建一个套接字并调用connect()
连接服务器时,客户端的操作系统会自动为客户端分配一个临时的本地端口(通常是 49152 到 65535 之间的动态端口),用于和服务器通信。 -
客户端使用这个临时端口来与服务器通信,而服务器则通过它的固定监听端口(比如 80 或 8080)接收客户端的请求。