用C语言如何实现聊天室登录、注册、退出、添加好友、私聊、群聊的代码,分客户端和服务器,并注释给我
时间: 2023-10-20 12:10:26 浏览: 251
聊天室程序C语言实现
5星 · 资源好评率100%
这是一个比较复杂的问题,需要很多的代码实现。
以下是一个简单的示例,仅供参考:
### 服务器端代码
```c
// 服务器端代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
#define MAX_CLIENTS 100
#define BUFFER_SIZE 1024
#define PORT 8888
struct client {
int socket;
char username[50];
};
struct client clients[MAX_CLIENTS];
int num_clients = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void handle_client(int socket);
void send_message(char *message, int sender_socket);
void send_private_message(char *message, char *recipient, int sender_socket);
void add_client(int socket);
void remove_client(int socket);
void broadcast(char *message, int sender_socket);
void list_clients(int socket);
void *client_thread(void *arg);
int main()
{
int server_socket, client_socket;
struct sockaddr_in server, client;
// 创建 socket
server_socket = socket(AF_INET, SOCK_STREAM, 0);
if (server_socket < 0) {
perror("Error creating socket");
exit(EXIT_FAILURE);
}
// 设置服务器地址
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(PORT);
// 绑定 socket
if (bind(server_socket, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("Error binding socket");
exit(EXIT_FAILURE);
}
// 开始监听
if (listen(server_socket, MAX_CLIENTS) < 0) {
perror("Error listening");
exit(EXIT_FAILURE);
}
printf("Server started on port %d\n", PORT);
// 处理客户端连接
while (1) {
// 接受客户端连接
int client_socket = accept(server_socket, (struct sockaddr *)&client, (socklen_t *)&client);
if (client_socket < 0) {
perror("Error accepting client");
continue;
}
// 创建线程处理客户端
pthread_t thread;
int *arg = malloc(sizeof(*arg));
*arg = client_socket;
pthread_create(&thread, NULL, client_thread, arg);
}
return 0;
}
void handle_client(int socket)
{
char buffer[BUFFER_SIZE];
char username[50];
int logged_in = 0;
// 循环处理客户端消息
while (1) {
memset(buffer, 0, BUFFER_SIZE);
// 接受消息
int bytes_received = recv(socket, buffer, BUFFER_SIZE, 0);
if (bytes_received < 0) {
perror("Error receiving message");
break;
} else if (bytes_received == 0) {
// 客户端已关闭连接
printf("Client %d disconnected\n", socket);
break;
}
// 处理消息
if (!logged_in) {
// 处理登录请求
if (strncmp(buffer, "login ", 6) == 0) {
// 获取用户名
char *username_start = buffer + 6;
char *username_end = strchr(buffer, ' ');
if (username_end == NULL || username_end - username_start > 50) {
send_message("Invalid username\n", socket);
continue;
}
strncpy(username, username_start, username_end - username_start);
username[username_end - username_start] = '\0';
// 判断用户名是否已存在
int i;
for (i = 0; i < num_clients; i++) {
if (strcmp(clients[i].username, username) == 0) {
send_message("Username already taken\n", socket);
break;
}
}
if (i < num_clients) {
continue;
}
// 添加客户端
add_client(socket);
strcpy(clients[num_clients - 1].username, username);
logged_in = 1;
sprintf(buffer, "Welcome, %s!\n", username);
send_message(buffer, socket);
broadcast(buffer, socket);
} else {
send_message("Please login first\n", socket);
}
} else {
// 处理其他命令
if (strncmp(buffer, "logout", 6) == 0) {
remove_client(socket);
sprintf(buffer, "%s has logged out\n", username);
broadcast(buffer, socket);
break;
} else if (strncmp(buffer, "add ", 4) == 0) {
char *friend_start = buffer + 4;
char *friend_end = strchr(buffer, ' ');
if (friend_end == NULL || friend_end - friend_start > 50) {
send_message("Invalid username\n", socket);
continue;
}
char friend_username[50];
strncpy(friend_username, friend_start, friend_end - friend_start);
friend_username[friend_end - friend_start] = '\0';
int i, found = 0;
for (i = 0; i < num_clients; i++) {
if (strcmp(clients[i].username, friend_username) == 0) {
found = 1;
break;
}
}
if (!found) {
send_message("User not found\n", socket);
continue;
}
sprintf(buffer, "%s has added you as a friend. Type 'accept %s' to accept the friend request\n", username, username);
send_message(buffer, clients[i].socket);
sprintf(buffer, "Friend request sent to %s\n", friend_username);
send_message(buffer, socket);
} else if (strncmp(buffer, "accept ", 7) == 0) {
char *friend_start = buffer + 7;
char *friend_end = strchr(buffer, ' ');
if (friend_end == NULL || friend_end - friend_start > 50) {
send_message("Invalid username\n", socket);
continue;
}
char friend_username[50];
strncpy(friend_username, friend_start, friend_end - friend_start);
friend_username[friend_end - friend_start] = '\0';
int i, found = 0;
for (i = 0; i < num_clients; i++) {
if (strcmp(clients[i].username, friend_username) == 0) {
found = 1;
break;
}
}
if (!found) {
send_message("User not found\n", socket);
continue;
}
sprintf(buffer, "%s has accepted your friend request\n", username);
send_message(buffer, clients[i].socket);
sprintf(buffer, "You are now friends with %s\n", friend_username);
send_message(buffer, socket);
} else if (strncmp(buffer, "list", 4) == 0) {
list_clients(socket);
} else if (strncmp(buffer, "private ", 8) == 0) {
char *recipient_start = buffer + 8;
char *recipient_end = strchr(buffer, ' ');
if (recipient_end == NULL || recipient_end - recipient_start > 50) {
send_message("Invalid username\n", socket);
continue;
}
char recipient[50];
strncpy(recipient, recipient_start, recipient_end - recipient_start);
recipient[recipient_end - recipient_start] = '\0';
char *message_start = recipient_end + 1;
if (strlen(message_start) == 0) {
send_message("Please enter a message\n", socket);
continue;
}
int i, found = 0;
for (i = 0; i < num_clients; i++) {
if (strcmp(clients[i].username, recipient) == 0) {
found = 1;
break;
}
}
if (!found) {
send_message("User not found\n", socket);
continue;
}
sprintf(buffer, "%s (private): %s\n", username, message_start);
send_private_message(buffer, recipient, socket);
} else {
sprintf(buffer, "%s: %s", username, buffer);
broadcast(buffer, socket);
}
}
}
}
void send_message(char *message, int sender_socket)
{
pthread_mutex_lock(&mutex);
send(sender_socket, message, strlen(message), 0);
pthread_mutex_unlock(&mutex);
}
void send_private_message(char *message, char *recipient, int sender_socket)
{
int i;
for (i = 0; i < num_clients; i++) {
if (strcmp(clients[i].username, recipient) == 0) {
send_message(message, clients[i].socket);
break;
}
}
if (i == num_clients) {
send_message("User not found\n", sender_socket);
}
}
void add_client(int socket)
{
pthread_mutex_lock(&mutex);
clients[num_clients].socket = socket;
num_clients++;
pthread_mutex_unlock(&mutex);
}
void remove_client(int socket)
{
pthread_mutex_lock(&mutex);
int i;
for (i = 0; i < num_clients; i++) {
if (clients[i].socket == socket) {
break;
}
}
if (i < num_clients - 1) {
clients[i] = clients[num_clients - 1];
}
num_clients--;
pthread_mutex_unlock(&mutex);
}
void broadcast(char *message, int sender_socket)
{
pthread_mutex_lock(&mutex);
int i;
for (i = 0; i < num_clients; i++) {
if (clients[i].socket != sender_socket) {
send_message(message, clients[i].socket);
}
}
pthread_mutex_unlock(&mutex);
}
void list_clients(int socket)
{
pthread_mutex_lock(&mutex);
char buffer[BUFFER_SIZE];
int i;
sprintf(buffer, "Current clients (%d):\n", num_clients);
send_message(buffer, socket);
for (i = 0; i < num_clients; i++) {
sprintf(buffer, "- %s\n", clients[i].username);
send_message(buffer, socket);
}
pthread_mutex_unlock(&mutex);
}
void *client_thread(void *arg)
{
int socket = *(int *)arg;
free(arg);
handle_client(socket);
close(socket);
return NULL;
}
```
### 客户端代码
```c
// 客户端代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
#define BUFFER_SIZE 1024
#define SERVER_ADDRESS "127.0.0.1"
#define PORT 8888
void *receive_thread(void *arg);
int main()
{
int socket_fd;
struct sockaddr_in server;
// 创建 socket
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (socket_fd < 0) {
perror("Error creating socket");
exit(EXIT_FAILURE);
}
// 设置服务器地址
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(SERVER_ADDRESS);
server.sin_port = htons(PORT);
// 连接服务器
if (connect(socket_fd, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("Error connecting to server");
exit(EXIT_FAILURE);
}
printf("Connected to server\n");
// 创建接收线程
pthread_t thread;
int *arg = malloc(sizeof(*arg));
*arg = socket_fd;
pthread_create(&thread, NULL, receive_thread, arg);
// 循环处理用户输入
char buffer[BUFFER_SIZE];
while (1) {
// 读取用户输入
fgets(buffer, BUFFER_SIZE, stdin);
buffer[strcspn(buffer, "\r\n")] = '\0';
// 发送消息
if (send(socket_fd, buffer, strlen(buffer), 0) < 0) {
perror("Error sending message");
exit(EXIT_FAILURE);
}
// 处理退出命令
if (strncmp(buffer, "logout", 6) == 0) {
break;
}
}
// 关闭连接
close(socket_fd);
return 0;
}
void *receive_thread(void *arg)
{
int socket_fd = *(int *)arg;
free(arg);
char buffer[BUFFER_SIZE];
int bytes_received;
while (1) {
memset(buffer, 0, BUFFER_SIZE);
// 接收消息
bytes_received = recv(socket_fd, buffer, BUFFER_SIZE, 0);
if (bytes_received < 0) {
perror("Error receiving message");
break;
} else if (bytes_received == 0) {
// 服务器已关闭连接
printf("Disconnected from server\n");
break;
}
// 输出消息
printf("%s", buffer);
}
return NULL;
}
```
以上代码仅供参考,实际上还有很多细节需要处理,例如:
- 用户名、密码的加密存储
- 好友关系的存储和管理
- 群聊的实现
- 多线程并发处理和同步等
如果您需要一个完整的聊天室系统,建议使用现成的开源软件或框架。
阅读全文