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)

{

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函数来实现非阻塞式通信。当