Linux网络编程之聊天程序(TCP协议之select)
client_addr;}// 设置服务器地址信息memset(&server_addr,sizeof(server_addr));
在当今互联网时代,聊天应用已经成为人们日常生活中不可或缺的一部分。而对于开发者来说,如何实现一个高效、稳定、安全的聊天程序则显得尤为重要。本文将以Linux网络编程为基础,介绍如何使用TCP协议和select函数来实现一个简单的聊天程序。
一、TCP协议
TCP(Transmission Control Protocol)是传输控制协议的缩写,它是一种面向连接的、可靠的传输层通信协议。在TCP连接中,数据可以被分割成多个数据包进行传输,并且可以确保每个数据包都能够到达接收方。此外,在发送端和接收端之间建立了一个虚拟连接(socket),从而保证了通信双方之间信息交流时不会出现混乱。
二、select函数
select函数是Linux系统提供给开发者用于异步I/O操作的一种机制。通过该函数,我们可以同时监听多个文件描述符上是否有事件发生,并在事件发生后做出相应处理。它常用于实现服务器端与客户端之间非阻塞式通信。
三、实现步骤
1. 创建服务器端和客户端socket,并绑定IP地址和端口号。
2. 使用select函数监听服务器端和客户端socket上是否有事件发生。
3. 当服务器端socket上有数据到达时,将数据发送给所有连接的客户端;当客户端socket上有数据到达时,将其显示在屏幕上并转发给其他连接的客户端。
4. 重复第2、3步,直到程序结束。
四、代码实现
以下是一个简单的聊天程序示例代码:
– 服务端代码
“`
#include
#include
#include
#include
#include
#include
#define PORT 8888
#define MAX_CLIENTS 100
int main()
{
int server_socket, client_socket[MAX_CLIENTS];
struct sockaddr_in server_addr, client_addr;
char buffer[1024] = {0};
fd_set readfds;
// 创建TCP socket
if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror(“Socket creation failed”);
exit(EXIT_FAILURE);
}
// 设置服务器地址信息
memset(&server_addr, ‘0’, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = INADDR_ANY;
// 绑定IP地址和端口号
if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1)
{
perror(“Bind failed”);
exit(EXIT_FAILURE);
}
// 监听socket
if (listen(server_socket, MAX_CLIENTS) == -1)
{
perror(“Listen failed”);
exit(EXIT_FAILURE);
}
// 初始化客户端socket数组
for (int i = 0; i < MAX_CLIENTS; i++)
client_socket[i] = 0;
while (1)
FD_ZERO(&readfds);
FD_SET(server_socket, &readfds);
int max_sd = server_socket;
// 添加所有有效的客户端socket到读集合中
for (int i = 0; i < MAX_CLIENTS; i++)
{
int sd = client_socket[i];
if (sd > 0)
{
FD_SET(sd, &readfds);
}
if (sd > max_sd)
max_sd = sd;
}
// 监听所有socket上是否有事件发生
int activity = select(max_sd + 1, &readfds, NULL, NULL, NULL);
if ((activity < 0) && (errno!=EINTR))
printf(“Select error”);
// 如果服务器端socket上有事件发生,说明有新的连接请求
if (FD_ISSET(server_socket, &readfds))
![Linux网络编程之聊天程序(TCP协议之select)缩略图 Linux网络编程之聊天程序(TCP协议之select)](https://www.72715.net/wp-content/uploads/2023/05/316b7ed716edfa48b7c74809ed2f3709.png)
{
int new_client;
socklen_t len=sizeof(client_addr);
if ((new_client=accept(server_socket,(struct sockaddr*)&client_addr,&len))==-1)
{
perror(“Accept failed”);
exit(EXIT_FAILURE);
}
printf(“New connection , socket fd is %d , ip is : %s , port : %dn”, new_client , inet_ntoa(client_addr.sin_addr) , ntohs(client_addr.sin_port));
for(int i=0;i<MAX_CLIENTS;i++)
{
// 将新的客户端加入到client_socket数组中
if(client_socket[i]==0)
{
client_socket[i]=new_client;
printf(“Adding to list of sockets as %dn” , i);
break;
}
}
// 处理所有连接的客户端socket上是否有事件发生
int sd = client_socket[i];
if (FD_ISSET(sd, &readfds))
int valread;
// 判断该客户端是否关闭了连接
if ((valread = read(sd, buffer, 1024)) == 0)
{
close(sd);
client_socket[i] = 0;
printf(“Client disconnectedn”);
}
// 将接收到的数据转发给其他连接的客户端
else
{
for(int j=0;j<MAX_CLIENTS;j++)
{
if(client_socket[j]!=sd && client_socket[j]>0)
{
send(client_socket[j], buffer, strlen(buffer), 0 );
}
}
}
}
}
}
return 0;
}
– 客户端代码
struct sockaddr_in server_addr;
char message[1024];
// 创建TCP socket
int sock = socket(AF_INET , SOCK_STREAM , 0);
// 设置服务器地址信息
// 将IP地址转换为二进制格式
if(inet_pton(AF_INET, “127.0.0.1”, &server_addr.sin_addr)<=0)
printf(“nInvalid address/ Address not supported n”);
return -1;
// 连接服务器
if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
printf(“nConnection Failed n”);
return -1;
while(1)
memset(message,’′,sizeof(message));
printf(“Enter message : “);
fgets(message,sizeof(message),stdin);
// 发送数据到服务器端
send(sock , message , strlen(message) , 0 );
// 接收从服务器端返回的数据
int valread = read( sock , buffer, 1024);
printf(“%sn”,buffer );
return 0;
五、总结
本文介绍了使用TCP协议和select函数来实现一个简单的聊天程序。通过以上示例代码,我们可以了解到如何创建socket、绑定IP地址和端口号、监听socket上是否有事件发生等基本操作,并且掌握了如何使用select函数来实现非阻塞式通信。当