Linux中利用C语言编写套接字通信程序,实现简单的文字发送、接收形式的会议功能。主持人运行服务器程序,参会者运行客户端程序。主持人发送的文字信息每个客户端用户都可以看到。任一客户端用户发送的文字信息包括主持人在内的其他参会者也都可以看到。服务器或者客户端显示当前开会人数,参会者标识,以及当前发送信息的程序或者用户的标识。
时间: 2023-06-25 15:05:52 浏览: 108
这是一个很好的练习项目,可以帮助你深入了解套接字通信和多线程编程。下面是一个简单的实现方案,仅供参考:
1. 服务器程序
服务器程序需要监听一个指定的端口,并在有新客户端连接时创建一个新的线程处理该客户端的请求。在处理请求时,服务器需要将客户端发送的消息广播给所有其他客户端。
以下是一个简单的服务器程序示例:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define MAX_CLIENTS 10
#define BUFFER_SIZE 1024
int client_count = 0;
int client_sockets[MAX_CLIENTS];
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void broadcast(char *message, int sender_socket) {
pthread_mutex_lock(&mutex);
for (int i = 0; i < client_count; i++) {
if (client_sockets[i] != sender_socket) {
send(client_sockets[i], message, strlen(message), 0);
}
}
pthread_mutex_unlock(&mutex);
}
void *handle_client(void *arg) {
int client_socket = *(int *)arg;
char buffer[BUFFER_SIZE];
pthread_mutex_lock(&mutex);
client_sockets[client_count++] = client_socket;
pthread_mutex_unlock(&mutex);
while (1) {
int ret = recv(client_socket, buffer, BUFFER_SIZE, 0);
if (ret <= 0) {
pthread_mutex_lock(&mutex);
for (int i = 0; i < client_count; i++) {
if (client_sockets[i] == client_socket) {
client_sockets[i] = client_sockets[--client_count];
break;
}
}
pthread_mutex_unlock(&mutex);
close(client_socket);
char message[100];
sprintf(message, "Client %d disconnected\n", client_socket);
broadcast(message, 0);
break;
} else {
buffer[ret] = '\0';
char message[100];
sprintf(message, "Client %d: %s", client_socket, buffer);
broadcast(message, client_socket);
}
}
return NULL;
}
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: %s port\n", argv[0]);
return 1;
}
int server_socket = socket(AF_INET, SOCK_STREAM, 0);
if (server_socket == -1) {
perror("socket");
return 1;
}
struct sockaddr_in server_addr = {
.sin_family = AF_INET,
.sin_port = htons(atoi(argv[1])),
.sin_addr.s_addr = INADDR_ANY,
};
if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("bind");
return 1;
}
if (listen(server_socket, 5) == -1) {
perror("listen");
return 1;
}
printf("Server started on port %s\n", argv[1]);
while (1) {
struct sockaddr_in client_addr;
socklen_t client_addr_len = sizeof(client_addr);
int client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &client_addr_len);
if (client_socket == -1) {
perror("accept");
continue;
}
char message[100];
sprintf(message, "Client %d connected\n", client_socket);
broadcast(message, 0);
pthread_t tid;
pthread_create(&tid, NULL, handle_client, &client_socket);
pthread_detach(tid);
}
close(server_socket);
return 0;
}
```
2. 客户端程序
客户端程序需要连接到服务器,并在输入文本后将其发送到服务器。客户端还需要接收来自服务器的消息并将其显示在屏幕上。
以下是一个简单的客户端程序示例:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define BUFFER_SIZE 1024
void *recv_thread(void *arg) {
int socket = *(int *)arg;
char buffer[BUFFER_SIZE];
while (1) {
int ret = recv(socket, buffer, BUFFER_SIZE, 0);
if (ret <= 0) {
printf("Disconnected from server\n");
break;
} else {
buffer[ret] = '\0';
printf("%s", buffer);
}
}
return NULL;
}
int main(int argc, char *argv[]) {
if (argc != 3) {
printf("Usage: %s host port\n", argv[0]);
return 1;
}
int client_socket = socket(AF_INET, SOCK_STREAM, 0);
if (client_socket == -1) {
perror("socket");
return 1;
}
struct sockaddr_in server_addr = {
.sin_family = AF_INET,
.sin_port = htons(atoi(argv[2])),
};
if (inet_pton(AF_INET, argv[1], &server_addr.sin_addr) != 1) {
perror("inet_pton");
return 1;
}
if (connect(client_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("connect");
return 1;
}
printf("Connected to server\n");
pthread_t tid;
pthread_create(&tid, NULL, recv_thread, &client_socket);
char buffer[BUFFER_SIZE];
while (1) {
fgets(buffer, BUFFER_SIZE, stdin);
send(client_socket, buffer, strlen(buffer), 0);
}
close(client_socket);
return 0;
}
```
注意:这只是一个简单的示例程序,可能存在一些安全问题和性能问题,如果你要用于实际应用中,请根据具体情况进行修改和优化。
阅读全文