编写套接字通信程序,实现简单的文字发送、接收形式的会议功能。主持人运行服务器程序,参会者运行客户端程序。主持人发送的文字信息每个客户端用户都可以看到。客户端用户发送的文字信息包括主持人在内的所有参会者也都可以看到。服务器端显示当前开会人数,参会者标识,以及当前发送信息的程序或者用户的标识。c语言实现套接字通信的,在Ubuntu上运行的。终端显示消息
时间: 2023-06-27 08:05:53 浏览: 99
这是一个比较复杂的任务,需要进行套接字编程和多线程编程。以下是一个简单的实现,供参考。
服务器端代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#define MAX_CLIENTS 10 // 最大客户端数量
#define BUFFER_SIZE 1024 // 缓冲区大小
int client_sockets[MAX_CLIENTS]; // 客户端套接字数组
pthread_t threads[MAX_CLIENTS]; // 线程数组
int num_clients = 0; // 当前客户端数量
void *handle_client(void *arg) {
int client_sock = *(int *)arg;
char buffer[BUFFER_SIZE];
int read_size;
// 接收客户端标识
read_size = recv(client_sock, buffer, BUFFER_SIZE, 0);
if (read_size <= 0) {
printf("Client disconnected\n");
return NULL;
}
buffer[read_size] = '\0';
printf("Client %s connected\n", buffer);
// 将客户端套接字加入数组
client_sockets[num_clients++] = client_sock;
// 接收并转发消息
while ((read_size = recv(client_sock, buffer, BUFFER_SIZE, 0)) > 0) {
buffer[read_size] = '\0';
printf("%s: %s\n", buffer, buffer + strlen(buffer) + 1);
for (int i = 0; i < num_clients; i++) {
if (client_sockets[i] != client_sock) {
send(client_sockets[i], buffer, strlen(buffer), 0);
}
}
}
// 将客户端套接字从数组中移除
for (int i = 0; i < num_clients; i++) {
if (client_sockets[i] == client_sock) {
for (int j = i + 1; j < num_clients; j++) {
client_sockets[j - 1] = client_sockets[j];
threads[j - 1] = threads[j];
}
num_clients--;
break;
}
}
printf("Client %s disconnected\n", buffer);
return NULL;
}
int main(int argc, char **argv) {
int server_sock, client_sock;
struct sockaddr_in server_addr, client_addr;
socklen_t client_addr_size = sizeof(client_addr);
if (argc != 2) {
printf("Usage: %s port\n", argv[0]);
return 1;
}
// 创建服务器套接字
if ((server_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
perror("socket");
return 1;
}
// 绑定地址和端口号
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(atoi(argv[1]));
if (bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("bind");
return 1;
}
// 监听连接请求
if (listen(server_sock, MAX_CLIENTS) < 0) {
perror("listen");
return 1;
}
printf("Server started\n");
// 接受连接请求并创建线程
while ((client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &client_addr_size)) >= 0) {
pthread_t thread;
if (pthread_create(&thread, NULL, handle_client, &client_sock) != 0) {
perror("pthread_create");
return 1;
}
threads[num_clients] = thread;
}
perror("accept");
return 1;
}
```
客户端代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define BUFFER_SIZE 1024 // 缓冲区大小
int main(int argc, char **argv) {
int server_sock;
struct sockaddr_in server_addr;
if (argc != 3) {
printf("Usage: %s host port\n", argv[0]);
return 1;
}
// 创建客户端套接字
if ((server_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
perror("socket");
return 1;
}
// 连接服务器
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(argv[1]);
server_addr.sin_port = htons(atoi(argv[2]));
if (connect(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("connect");
return 1;
}
// 发送客户端标识
char buffer[BUFFER_SIZE];
printf("Enter your name: ");
fgets(buffer, BUFFER_SIZE, stdin);
buffer[strlen(buffer) - 1] = '\0'; // 去掉换行符
send(server_sock, buffer, strlen(buffer), 0);
// 接收并显示消息
while (1) {
printf("> ");
fgets(buffer, BUFFER_SIZE, stdin);
buffer[strlen(buffer) - 1] = '\0'; // 去掉换行符
send(server_sock, buffer, strlen(buffer) + 1 + strlen(buffer), 0); // 发送标识和消息
}
return 0;
}
```
编译命令:
```
gcc server.c -o server -lpthread
gcc client.c -o client
```
运行命令:
```
./server <port>
./client <host> <port>
```
其中,`<port>` 是服务器监听的端口号,`<host>` 和 `<port>` 是服务器的地址和端口号。客户端会提示输入用户名,然后可以发送消息,在终端上显示所有消息。服务器会显示当前客户端数量、客户端标识和当前发送消息的客户端标识。
阅读全文