基于Linux下的多进程多线程的聊天室: 服务器:1个 客户端:2~3个(演示时2~3个,实际是可以支持多用户连接登录的)可群聊与私聊的C语言代码
时间: 2024-05-07 10:20:04 浏览: 112
以下是一个基于Linux下的多进程多线程的聊天室的简单实现。代码使用C语言编写。
服务器代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAX_CLIENTS 10
#define MAX_MSG_LEN 256
int client_count = 0;
int client_fds[MAX_CLIENTS];
pthread_t threads[MAX_CLIENTS];
void *handle_client(void *arg)
{
int client_fd = *(int *)arg;
int i, len;
char msg[MAX_MSG_LEN + 1];
while ((len = read(client_fd, msg, MAX_MSG_LEN)) > 0) {
msg[len] = '\0';
if (strcmp(msg, "quit") == 0) {
break;
}
for (i = 0; i < client_count; i++) {
if (client_fds[i] != client_fd) {
write(client_fds[i], msg, strlen(msg));
}
}
}
for (i = 0; i < client_count; i++) {
if (client_fds[i] == client_fd) {
client_fds[i] = -1;
break;
}
}
client_count--;
close(client_fd);
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
int server_fd, client_fd, port, i;
struct sockaddr_in server_addr, client_addr;
socklen_t client_len;
if (argc != 2) {
fprintf(stderr, "Usage: %s port\n", argv[0]);
exit(EXIT_FAILURE);
}
port = atoi(argv[1]);
server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == -1) {
perror("socket");
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;
if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("bind");
exit(EXIT_FAILURE);
}
if (listen(server_fd, MAX_CLIENTS) == -1) {
perror("listen");
exit(EXIT_FAILURE);
}
printf("Server started on port %d...\n", port);
while (1) {
client_len = sizeof(client_addr);
client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_len);
if (client_fd == -1) {
perror("accept");
continue;
}
if (client_count == MAX_CLIENTS) {
printf("Max client count reached, closing new connection...\n");
close(client_fd);
continue;
}
for (i = 0; i < MAX_CLIENTS; i++) {
if (client_fds[i] == -1) {
client_fds[i] = client_fd;
pthread_create(&threads[i], NULL, handle_client, (void *)&client_fd);
client_count++;
break;
}
}
printf("New client connected, count: %d\n", client_count);
}
close(server_fd);
return 0;
}
```
客户端代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAX_MSG_LEN 256
void *handle_input(void *arg)
{
int server_fd = *(int *)arg;
int len;
char msg[MAX_MSG_LEN + 1];
while (fgets(msg, MAX_MSG_LEN, stdin)) {
len = strlen(msg);
if (msg[len - 1] == '\n') {
msg[len - 1] = '\0';
}
write(server_fd, msg, strlen(msg));
}
write(server_fd, "quit", strlen("quit"));
close(server_fd);
pthread_exit(NULL);
}
void *handle_output(void *arg)
{
int server_fd = *(int *)arg;
int len;
char msg[MAX_MSG_LEN + 1];
while ((len = read(server_fd, msg, MAX_MSG_LEN)) > 0) {
msg[len] = '\0';
printf("%s\n", msg);
}
close(server_fd);
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
int server_fd, port;
struct sockaddr_in server_addr;
if (argc != 3) {
fprintf(stderr, "Usage: %s host port\n", argv[0]);
exit(EXIT_FAILURE);
}
port = atoi(argv[2]);
server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
if (inet_pton(AF_INET, argv[1], &server_addr.sin_addr) != 1) {
perror("inet_pton");
exit(EXIT_FAILURE);
}
if (connect(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("connect");
exit(EXIT_FAILURE);
}
pthread_t input_thread, output_thread;
pthread_create(&input_thread, NULL, handle_input, (void *)&server_fd);
pthread_create(&output_thread, NULL, handle_output, (void *)&server_fd);
pthread_join(input_thread, NULL);
pthread_join(output_thread, NULL);
return 0;
}
```
编译命令:
```
gcc server.c -o server -lpthread
gcc client.c -o client -lpthread
```
运行命令:
```
./server <port>
./client <host> <port>
```
注意:在服务器端和客户端中,`<port>` 均为要监听的端口号,`<host>` 均为服务器的IP地址。在客户端中输入消息后按回车发送,输入 `quit` 退出。
阅读全文