编写套接字通信程序,实现简单的文字发送、接收形式的会议功能。主持人运行服务器程序,参会者运行客户端程序。服务器端主持人发送信息所有人都可以看到。客户端用户发送的文字信息包括主持人在内的所有参会者也都可以看到。服务器端显示当前开会人数,参会者标识,以及当前发送信息的程序或者用户的标识。c语言,在Ubuntu上运行的。终端显示消息
时间: 2023-07-14 13:14:08 浏览: 64
下面是一个简单的套接字通信程序,实现了文字发送、接收形式的会议功能。主持人运行服务器程序,参会者运行客户端程序。服务器端主持人发送信息所有人都可以看到。客户端用户发送的文字信息包括主持人在内的所有参会者也都可以看到。服务器端显示当前开会人数,参会者标识,以及当前发送信息的程序或者用户的标识。
服务器端程序:
```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 clients[MAX_CLIENTS];
int num_clients = 0;
pthread_mutex_t mutex;
void error(char *message) {
perror(message);
exit(1);
}
void send_message(char *message, int sender) {
pthread_mutex_lock(&mutex);
for (int i = 0; i < num_clients; i++) {
if (clients[i] != sender) {
if (send(clients[i], message, strlen(message), 0) == -1) {
perror("send");
}
}
}
pthread_mutex_unlock(&mutex);
}
void *handle_client(void *arg) {
int client_sockfd = *(int *) arg;
char buffer[BUFFER_SIZE];
while (1) {
memset(buffer, 0, BUFFER_SIZE);
int recv_len = recv(client_sockfd, buffer, BUFFER_SIZE, 0);
if (recv_len == -1) {
perror("recv");
break;
} else if (recv_len == 0) {
printf("Client disconnected: %d\n", client_sockfd);
break;
} else {
send_message(buffer, client_sockfd);
}
}
pthread_mutex_lock(&mutex);
for (int i = 0; i < num_clients; i++) {
if (clients[i] == client_sockfd) {
clients[i] = clients[num_clients - 1];
num_clients--;
break;
}
}
pthread_mutex_unlock(&mutex);
close(client_sockfd);
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <port>\n", argv[0]);
exit(1);
}
int server_sockfd, client_sockfd;
struct sockaddr_in server_addr, client_addr;
socklen_t client_len = sizeof(client_addr);
pthread_t threads[MAX_CLIENTS];
if ((server_sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
error("socket");
}
int port = atoi(argv[1]);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(port);
if (bind(server_sockfd, (struct sockaddr *) &server_addr, sizeof(server_addr)) == -1) {
error("bind");
}
if (listen(server_sockfd, MAX_CLIENTS) == -1) {
error("listen");
}
printf("Server listening on port %d...\n", port);
pthread_mutex_init(&mutex, NULL);
while (1) {
if ((client_sockfd = accept(server_sockfd, (struct sockaddr *) &client_addr, &client_len)) == -1) {
error("accept");
}
pthread_mutex_lock(&mutex);
clients[num_clients++] = client_sockfd;
pthread_mutex_unlock(&mutex);
printf("Client connected: %d\n", client_sockfd);
pthread_create(&threads[num_clients - 1], NULL, handle_client, &client_sockfd);
}
pthread_mutex_destroy(&mutex);
close(server_sockfd);
return 0;
}
```
客户端程序:
```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
void error(char *message) {
perror(message);
exit(1);
}
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: %s <server-ip> <port>\n", argv[0]);
exit(1);
}
int sockfd;
struct sockaddr_in server_addr;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
error("socket");
}
int port = atoi(argv[2]);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(argv[1]);
server_addr.sin_port = htons(port);
if (connect(sockfd, (struct sockaddr *) &server_addr, sizeof(server_addr)) == -1) {
error("connect");
}
char username[BUFFER_SIZE];
printf("Enter your username: ");
fgets(username, BUFFER_SIZE, stdin);
username[strlen(username) - 1] = '\0';
char buffer[BUFFER_SIZE];
while (1) {
printf("> ");
fgets(buffer, BUFFER_SIZE, stdin);
buffer[strlen(buffer) - 1] = '\0';
if (send(sockfd, buffer, strlen(buffer), 0) == -1) {
error("send");
}
int recv_len = recv(sockfd, buffer, BUFFER_SIZE, 0);
if (recv_len == -1) {
perror("recv");
break;
} else if (recv_len == 0) {
printf("Server disconnected\n");
break;
} else {
printf("[%s]: %s\n", username, buffer);
}
}
close(sockfd);
return 0;
}
```
使用方法:
1. 在终端启动服务器端程序,指定监听的端口号:
```
$ ./server 8000
```
2. 在另一个终端启动客户端程序,指定服务器的 IP 地址和端口号:
```
$ ./client 127.0.0.1 8000
```
3. 输入用户名后,即可进行文字交流。
注意事项:
1. 该程序使用了多线程和互斥锁机制,可以支持多个客户端同时连接和交流。
2. 程序中的错误处理比较简单,实际使用时需要加强。