为什么 accept() 创建一个新的套接字?
Why does accept() create a new socket?
此图演示了来自Linux编程接口
的典型客户端-服务器模型
这是来自 geeksforgeeks
的服务器端示例源代码
#include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#define MAX 80
#define PORT 8080
#define SA struct sockaddr
// Function designed for a chat between client and server.
void func(int sockfd)
{
// server's job
}
// Driver function
int main()
{
int sockfd, connfd, len;
struct sockaddr_in servaddr, cli;
// socket create and verification
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
printf("socket creation failed...\n");
exit(0);
}
else
printf("Socket successfully created..\n");
bzero(&servaddr, sizeof(servaddr));
// assign IP, PORT
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(PORT);
// Binding newly created socket to given IP and verification
if ((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0) {
printf("socket bind failed...\n");
exit(0);
}
else
printf("Socket successfully binded..\n");
// Now server is ready to listen and verification
if ((listen(sockfd, 5)) != 0) {
printf("Listen failed...\n");
exit(0);
}
else
printf("Server listening..\n");
len = sizeof(cli);
// Accept the data packet from client and verification
connfd = accept(sockfd, (SA*)&cli, &len);
if (connfd < 0) {
printf("server acccept failed...\n");
exit(0);
}
else
printf("server acccept the client...\n");
// Function for chatting between client and server
func(connfd);
// After chatting close the socket
close(sockfd);
}
在我上面提到的那本书里,作者说
The key point to understand about accept() is that it creates a new socket, and it is
this new socket that is connected to the peer socket that performed the connect().
在服务器的源代码中,有 2 个套接字
sockfd
,socket()
的输出
connfd
,accept()
的输出
为什么服务器端不使用 sockfd
与客户端“对话”,而是创建一个新的套接字 - connfd
然后在已经存在套接字的情况下与客户端“对话” ?
一个服务器可以同时连接多个客户端。单个套接字描述符不能表示多个连接。每个连接都由本地 + 对等 address/port 对的唯一组合组成,因此服务器需要一个单独的套接字描述符来表示每个连接。
一个侦听套接字可用于接受多个连接,每个连接具有不同的远程 IP/port 对。
TCP 连接由 4 个值定义:源 IP、源端口、目标 IP、目标端口。 accept
返回的套接字描述符与此类连接相关联。相比之下,侦听套接字仅与本地IP和端口相关联。
在这个特定的代码示例中,它只调用了一次 accept
。但它可以循环处理来自多个端点的连接。通常,这样的进程将有一个线程在循环中调用 accept
。然后,当从 accept
返回一个新套接字时,将启动一个新线程来处理该连接,同时主线程再次调用 accept
。
此图演示了来自Linux编程接口
的典型客户端-服务器模型这是来自 geeksforgeeks
的服务器端示例源代码#include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#define MAX 80
#define PORT 8080
#define SA struct sockaddr
// Function designed for a chat between client and server.
void func(int sockfd)
{
// server's job
}
// Driver function
int main()
{
int sockfd, connfd, len;
struct sockaddr_in servaddr, cli;
// socket create and verification
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
printf("socket creation failed...\n");
exit(0);
}
else
printf("Socket successfully created..\n");
bzero(&servaddr, sizeof(servaddr));
// assign IP, PORT
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(PORT);
// Binding newly created socket to given IP and verification
if ((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0) {
printf("socket bind failed...\n");
exit(0);
}
else
printf("Socket successfully binded..\n");
// Now server is ready to listen and verification
if ((listen(sockfd, 5)) != 0) {
printf("Listen failed...\n");
exit(0);
}
else
printf("Server listening..\n");
len = sizeof(cli);
// Accept the data packet from client and verification
connfd = accept(sockfd, (SA*)&cli, &len);
if (connfd < 0) {
printf("server acccept failed...\n");
exit(0);
}
else
printf("server acccept the client...\n");
// Function for chatting between client and server
func(connfd);
// After chatting close the socket
close(sockfd);
}
在我上面提到的那本书里,作者说
The key point to understand about accept() is that it creates a new socket, and it is this new socket that is connected to the peer socket that performed the connect().
在服务器的源代码中,有 2 个套接字
sockfd
,socket()
的输出
connfd
,accept()
的输出
为什么服务器端不使用 sockfd
与客户端“对话”,而是创建一个新的套接字 - connfd
然后在已经存在套接字的情况下与客户端“对话” ?
一个服务器可以同时连接多个客户端。单个套接字描述符不能表示多个连接。每个连接都由本地 + 对等 address/port 对的唯一组合组成,因此服务器需要一个单独的套接字描述符来表示每个连接。
一个侦听套接字可用于接受多个连接,每个连接具有不同的远程 IP/port 对。
TCP 连接由 4 个值定义:源 IP、源端口、目标 IP、目标端口。 accept
返回的套接字描述符与此类连接相关联。相比之下,侦听套接字仅与本地IP和端口相关联。
在这个特定的代码示例中,它只调用了一次 accept
。但它可以循环处理来自多个端点的连接。通常,这样的进程将有一个线程在循环中调用 accept
。然后,当从 accept
返回一个新套接字时,将启动一个新线程来处理该连接,同时主线程再次调用 accept
。