编写套接字通信程序,实现简单的文字发送、接收形式的会议功能。主持人运行服务器程序,参会者运行客户端程序。主持人发送的文字信息每个客户端用户都可以看到。任一客户端用户发送的文字信息包括主持人在内的其他参会者也都可以看到。服务器或者客户端显示当前开会人数,参会者标识,以及当前发送信息的程序或者用户的标识。c语言实现套接字通信的,在Ubuntu上运行的。终端显示消息。服务器也能像客户一样收发信息
时间: 2023-06-27 22:06:25 浏览: 138
这是一个比较复杂的程序,需要用到多线程和套接字编程。下面是一个简单的代码示例,可以作为参考:
服务器端代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#define MAX_CLIENTS 10
#define BUF_SIZE 256
int client_count = 0;
int client_sockets[MAX_CLIENTS];
char *client_names[MAX_CLIENTS];
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *handle_client(void *arg)
{
int client_socket = *(int *)arg;
char buf[BUF_SIZE];
int len;
// 新客户端连接,获取其名称
pthread_mutex_lock(&mutex);
client_sockets[client_count] = client_socket;
client_names[client_count] = malloc(BUF_SIZE);
sprintf(client_names[client_count], "client%d", client_count);
client_count++;
pthread_mutex_unlock(&mutex);
// 发送欢迎消息
sprintf(buf, "Welcome to the chat room! Your name is %s.\n", client_names[client_count-1]);
write(client_socket, buf, strlen(buf));
// 接收并转发消息
while ((len = read(client_socket, buf, BUF_SIZE)) > 0) {
buf[len] = '\0';
pthread_mutex_lock(&mutex);
for (int i = 0; i < client_count; i++) {
if (client_sockets[i] != client_socket) {
sprintf(buf, "[%s]: %s", client_names[client_count-1], buf);
write(client_sockets[i], buf, strlen(buf));
}
}
pthread_mutex_unlock(&mutex);
}
// 客户端退出,释放资源
close(client_socket);
pthread_mutex_lock(&mutex);
for (int i = 0; i < client_count; i++) {
if (client_sockets[i] == client_socket) {
free(client_names[i]);
client_count--;
for (int j = i; j < client_count; j++) {
client_sockets[j] = client_sockets[j+1];
client_names[j] = client_names[j+1];
}
break;
}
}
pthread_mutex_unlock(&mutex);
return NULL;
}
int main()
{
int server_socket, client_socket;
struct sockaddr_in server_addr, client_addr;
socklen_t addr_len = sizeof(client_addr);
pthread_t client_thread;
// 创建服务器套接字
if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
exit(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(8888);
if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("bind");
exit(1);
}
// 监听客户端连接
if (listen(server_socket, MAX_CLIENTS) < 0) {
perror("listen");
exit(1);
}
// 处理客户端连接
while (1) {
if ((client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &addr_len)) < 0) {
perror("accept");
exit(1);
}
pthread_create(&client_thread, NULL, handle_client, &client_socket);
}
return 0;
}
```
客户端代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#define BUF_SIZE 256
int client_socket;
char name[BUF_SIZE];
void *recv_thread(void *arg)
{
char buf[BUF_SIZE];
int len;
while ((len = read(client_socket, buf, BUF_SIZE)) > 0) {
buf[len] = '\0';
printf("%s", buf);
}
return NULL;
}
int main(int argc, char *argv[])
{
struct sockaddr_in server_addr;
pthread_t recv_thread_id;
char buf[BUF_SIZE];
int len;
// 创建客户端套接字
if ((client_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
exit(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(8888);
if (connect(client_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("connect");
exit(1);
}
// 接收欢迎消息,并输入自己的名字
if ((len = read(client_socket, buf, BUF_SIZE)) <= 0) {
perror("read");
exit(1);
}
buf[len] = '\0';
printf("%s", buf);
printf("Please enter your name: ");
fgets(name, BUF_SIZE, stdin);
name[strcspn(name, "\n")] = '\0';
// 启动接收线程
pthread_create(&recv_thread_id, NULL, recv_thread, NULL);
// 发送消息
while (fgets(buf, BUF_SIZE, stdin) != NULL) {
sprintf(buf, "[%s]: %s", name, buf);
write(client_socket, buf, strlen(buf));
}
// 关闭客户端套接字
close(client_socket);
return 0;
}
```
注意:以上代码只是一个简单的示例,并没有考虑异常情况的处理,例如客户端连接中断、服务器崩溃等。在实际应用中还需要根据具体情况进行完善。
阅读全文