Socket编程疑问:新建socket fd能否永久复用及多操作实现
Socket编程基础聊天程序疑问解答
我正在学习Socket编程,编写了一个客户端与服务器的基础聊天程序(暂不考虑发布),以下是我的代码片段:
服务端代码片段
// 省略初始化监听套接字等前置代码 new_socket = accept(server_fd, (struct sockaddr*)&address,(socklen_t*)&addrlen); char server_msg[128]; char client_msg[128]; int running = 1; while(running){ fgets(server_msg, 64, stdin); send(new_socket, server_msg, strlen(server_msg), 0); recv(new_socket, client_msg, 128, 0); }
客户端代码片段
char server_msg[128]; char client_msg[128]; int running = 1; while(running){ fgets(client_msg, 64, stdin); send(server_socket, client_msg, strlen(client_msg), 0); recv(server_socket, server_msg, 128, 0); }
疑问解答
新建的socket fd是否只能使用一次?即是否需要每次收发消息都创建新的socket,还是可以永久复用该socket fd?
完全不需要每次收发都创建新socket。accept返回的new_socket是和当前客户端建立的连接套接字,只要TCP连接没断开(双方没调用close),这个fd就可以一直用来收发消息,直到连接关闭。服务器的监听套接字server_fd也会一直存在,专门用来接收新的客户端连接请求。若该socket fd可永久复用,是否需要对其执行如清空之类的操作?
socket fd本身是一个整数标识,不需要做清空操作。但要注意每次收发前清空存储消息的缓冲区数组(比如你的server_msg、client_msg)。因为recv会把数据写入缓冲区,上次接收的残留数据可能会和新消息混在一起,导致解析错误。比如可以用memset(client_msg, 0, sizeof(client_msg))在每次调用recv前清空缓冲区。当前代码运行正常,但如何实现输入、发送消息、接收消息这类中断操作?
当前代码是阻塞式逻辑:服务端发完消息后会卡在recv,必须等客户端发消息才能继续输入;客户端同理,发完消息就等着收消息,没法在等待时输入新内容。要实现同时处理输入和接收,常用方案有三种:
- 多线程/多进程:开一个线程专门负责从
stdin读取输入并发送,另一个线程专门负责接收socket消息并打印。比如用pthread_create创建两个线程,分别处理不同的IO操作。 - IO多路复用:用
select、poll(跨平台)或epoll(Linux专属)同时监听标准输入的文件描述符(0)和socket fd。当其中任意一个有数据可读时,再触发对应的处理逻辑。 - 非阻塞socket:把socket设置为非阻塞模式(用
fcntl修改O_NONBLOCK标志),然后在循环里轮询检查socket是否有消息可读,同时处理输入。这种方式效率较低,一般只在特定场景使用。
内容的提问来源于stack exchange,提问作者suiciyom
相关产品推荐
相关产品推荐

