编写一个聊天服务器和聊天的客户端,实现基本的即时聊天功能。服务器在一个端口上进行监听,接收客户端的连接请求;客户端连接到服务器,发布自己的消息;服务器接收客户端的消息并转发给其他客户端。
时间: 2024-03-08 09:51:01 浏览: 225
FreddiChat:FreddiChat是使用WCF和WPF用C#编写的简单聊天客户端和服务器解决方案。 它使用NetNamedPipeBinding,NetTcpBinding或WSDualHttpBinding进行连接
好的,我可以给你提供一个简单的C语言实现的聊天服务器和客户端代码。这里使用TCP协议来实现通信。注意,这个示例代码只是一个简单的演示,没有考虑安全性和错误处理等问题,需要你根据具体需求进行修改和完善。
聊天服务器代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <pthread.h>
#define MAX_CLIENTS 10
#define MAX_MSG_LEN 1024
#define PORT 8080
struct client_info {
int sock_fd;
char name[20];
};
struct client_info clients[MAX_CLIENTS];
int num_clients = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
// 处理客户端的消息
void handle_client_msg(int client_fd, char *name) {
char buf[MAX_MSG_LEN];
int num_bytes;
while (1) {
// 从客户端接收消息
num_bytes = recv(client_fd, buf, MAX_MSG_LEN, 0);
if (num_bytes <= 0) {
// 客户端断开连接,从客户端列表中删除该客户端
pthread_mutex_lock(&mutex);
for (int i = 0; i < num_clients; i++) {
if (clients[i].sock_fd == client_fd) {
printf("%s disconnected.\n", clients[i].name);
// 将该客户端从客户端列表中删除
for (int j = i; j < num_clients - 1; j++) {
clients[j] = clients[j + 1];
}
num_clients--;
break;
}
}
pthread_mutex_unlock(&mutex);
break;
}
// 将消息转发给其他客户端
pthread_mutex_lock(&mutex);
for (int i = 0; i < num_clients; i++) {
if (clients[i].sock_fd != client_fd) {
// 发送消息给其他客户端
sprintf(buf, "%s: %s", name, buf);
send(clients[i].sock_fd, buf, strlen(buf), 0);
}
}
pthread_mutex_unlock(&mutex);
}
}
// 处理客户端的连接请求
void handle_client_connect(int client_fd) {
struct sockaddr_in client_addr;
socklen_t addr_len = sizeof(client_addr);
char buf[MAX_MSG_LEN];
int num_bytes;
// 接收客户端的昵称
num_bytes = recv(client_fd, buf, MAX_MSG_LEN, 0);
if (num_bytes <= 0) {
// 客户端断开连接
close(client_fd);
return;
}
buf[num_bytes] = '\0';
// 将客户端加入客户端列表
pthread_mutex_lock(&mutex);
if (num_clients >= MAX_CLIENTS) {
// 客户端列表已满,拒绝连接
close(client_fd);
pthread_mutex_unlock(&mutex);
return;
}
clients[num_clients].sock_fd = client_fd;
strncpy(clients[num_clients].name, buf, sizeof(clients[num_clients].name) - 1);
num_clients++;
printf("%s connected.\n", buf);
pthread_mutex_unlock(&mutex);
// 处理客户端的消息
handle_client_msg(client_fd, buf);
}
int main(int argc, char *argv[]) {
int server_fd, client_fd;
struct sockaddr_in server_addr, client_addr;
socklen_t addr_len = sizeof(client_addr);
pthread_t tid;
// 创建套接字
server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
// 绑定套接字到端口
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(PORT);
if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("bind");
exit(EXIT_FAILURE);
}
// 监听端口
if (listen(server_fd, MAX_CLIENTS) == -1) {
perror("listen");
exit(EXIT_FAILURE);
}
printf("Chat server started on port %d.\n", PORT);
while (1) {
// 接受客户端连接请求
client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &addr_len);
if (client_fd == -1) {
perror("accept");
continue;
}
// 创建一个线程来处理客户端连接
if (pthread_create(&tid, NULL, (void *)handle_client_connect, (void *)client_fd) != 0) {
perror("pthread_create");
continue;
}
// 分离线程
pthread_detach(tid);
}
return 0;
}
```
聊天客户端代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <pthread.h>
#define MAX_MSG_LEN 1024
#define PORT 8080
// 处理从服务器接收到的消息
void handle_server_msg(int sock_fd) {
char buf[MAX_MSG_LEN];
int num_bytes;
while (1) {
// 从服务器接收消息
num_bytes = recv(sock_fd, buf, MAX_MSG_LEN, 0);
if (num_bytes <= 0) {
// 服务器断开连接
printf("Server disconnected.\n");
break;
}
buf[num_bytes] = '\0';
// 显示消息
printf("%s\n", buf);
}
}
int main(int argc, char *argv[]) {
int sock_fd;
struct sockaddr_in server_addr;
char name[20], buf[MAX_MSG_LEN];
pthread_t tid;
int num_bytes;
if (argc != 3) {
fprintf(stderr, "Usage: %s <name> <server_ip>\n", argv[0]);
exit(EXIT_FAILURE);
}
// 获取用户名
strncpy(name, argv[1], sizeof(name) - 1);
// 创建套接字
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if (sock_fd == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
// 连接服务器
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(argv[2]);
server_addr.sin_port = htons(PORT);
if (connect(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("connect");
exit(EXIT_FAILURE);
}
// 发送昵称给服务器
if (send(sock_fd, name, strlen(name), 0) == -1) {
perror("send");
exit(EXIT_FAILURE);
}
// 创建一个线程来处理从服务器接收到的消息
if (pthread_create(&tid, NULL, (void *)handle_server_msg, (void *)sock_fd) != 0) {
perror("pthread_create");
exit(EXIT_FAILURE);
}
// 循环读取用户输入并发送给服务器
while (1) {
fgets(buf, MAX_MSG_LEN, stdin);
num_bytes = strlen(buf);
if (num_bytes > 0 && buf[num_bytes - 1] == '\n') {
buf[num_bytes - 1] = '\0';
num_bytes--;
}
if (num_bytes == 0) {
continue;
}
// 发送消息给服务器
if (send(sock_fd, buf, num_bytes, 0) == -1) {
perror("send");
exit(EXIT_FAILURE);
}
}
return 0;
}
```
希望这个示例代码能够对你有所帮助。
阅读全文