网络通讯项目源码
编译
gcc chat_server.c(服务端) -o server(服务端可执行文件) -pthread临时升级 系统 gcc 的版本
sudo yum install centos-release-scl
sudo yum install devtoolset-9-gcc*
scl enable devtoolset-9 bash服务端源码
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <pthread.h>
#include <time.h> // 用于时间函数
// 全局文件指针
FILE *fp;
// 结构体,用于保存用户信息
struct User {
char ip[INET_ADDRSTRLEN]; // IP地址字符串
char username[50]; // 用户选择的用户名
int connfd; // 连接套接字描述符
};
// 数组,用于存储注册用户(为简单起见,考虑使用动态数据结构以提升可扩展性)
struct User registeredUsers[100]; // 假设最多100个用户
// 注册用户计数
int numRegisteredUsers = 0;
// 写用户信息到文件的函数
void writeUserToFile(struct User user) {
FILE *file = fopen("registered_users.txt", "a"); // 'a' 追加模式
if (file == NULL) {
perror("文件打开");
return;
}
fprintf(file, "IP: %s, 用户名: %s\n", user.ip, user.username);
fclose(file);
}
// 发送私聊消息的函数
void sendPrivateMessage(char* sender, char* receiver, char* message) {
// 查找接收者的连接套接字描述符
int receiverConnfd = -1;
for (int i = 0; i < numRegisteredUsers; i++) {
if (strcmp(registeredUsers[i].username, receiver) == 0) {
receiverConnfd = registeredUsers[i].connfd;
break;
}
}
// 如果找到接收者,发送私聊消息
if (receiverConnfd != -1) {
char privateMessage[BUFSIZ];
sprintf(privateMessage, "[私聊] %s 对你说: %s\n", sender, message);
send(receiverConnfd, privateMessage, strlen(privateMessage), 0);
} else {
printf("找不到用户 %s\n", receiver);
}
}
// 处理客户端连接的函数
void* handleClientConnection(void *arg) {
int connfd = *(int*)arg;
free(arg);
struct sockaddr_in client;
socklen_t clientLength = sizeof(client);
if (getpeername(connfd, (struct sockaddr*)&client, &clientLength) == -1) {
perror("获取客户端地址失败");
close(connfd);
return NULL;
}
char buf[BUFSIZ];
char timestamp[20]; // 时间戳缓冲区
char username[50]; // 用户名缓冲区
// 提示用户输入用户名
sprintf(buf, "请输入您的用户名: ");
send(connfd, buf, strlen(buf), 0);
// 从客户端接收用户名
int receivedBytes = recv(connfd, username, sizeof(username) - 1, 0);
if (receivedBytes <= 0) {
perror("接收用户名错误");
close(connfd);
return NULL;
}
username[receivedBytes] = '\0'; // 添加字符串结束符
// 存储用户信息并写入文件
strcpy(registeredUsers[numRegisteredUsers].ip, inet_ntoa(client.sin_addr));
strcpy(registeredUsers[numRegisteredUsers].username, username);
registeredUsers[numRegisteredUsers].connfd = connfd; // 存储连接套接字描述符
writeUserToFile(registeredUsers[numRegisteredUsers]);
numRegisteredUsers++;
int registered = 0; // 标志位,指示用户是否已注册
while (!registered) {
// 检查用户是否已注册
for (int i = 0; i < numRegisteredUsers; i++) {
if (strcmp(registeredUsers[i].username, username) == 0) {
registered = 1;
break;
}
}
}
while (1) {
bzero(buf, sizeof(buf));
int receivedBytes = recv(connfd, buf, sizeof(buf), 0);
if (receivedBytes == -1) {
perror("服务器接收错误");
}
else if (receivedBytes == 0) {
printf("客户端已断开连接\n");
break;
}
else {
// 判断是否为私聊消息
if (buf[0] == '@') {
char* receiver = strtok(buf + 1, " "); // 提取接收者用户名(跳过@符号)
char* message = strtok(NULL, ""); // 提取私聊消息内容
if (receiver != NULL && message != NULL && strtok(NULL, "") == NULL) {
sendPrivateMessage(username, receiver, message); // 发送私聊消息
} else {
printf("私聊消息格式不正确\n");
send(connfd, "私聊消息格式不正确\n", strlen("私聊消息格式不正确\n"), 0);
}
} else {
// 获取当前时间
time_t now = time(NULL);
struct tm *timeInfo = localtime(&now);
char timestamp[20];
strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", timeInfo);
// 输出到控制台
printf("[%s] %3s (%s): %s\n", timestamp, username, inet_ntoa(client.sin_addr), buf);
// 写入带时间戳的文件
fprintf(fp, "[%s] %3s (%s): %s\n", timestamp, username, inet_ntoa(client.sin_addr), buf);
fflush(fp); // 确保立即写入数据
}
}
}
close(connfd);
return NULL;
}
int main() {
int tcpsocket = socket(AF_INET, SOCK_STREAM, 0);
if (tcpsocket == -1) {
perror("socket");
return -1;
}
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(9999);
server.sin_addr.s_addr = inet_addr("172.19.10.249");
int ret = bind(tcpsocket, (struct sockaddr *)&server, sizeof(server));
if (ret == -1) {
perror("bind");
return -1;
}
ret = listen(tcpsocket, 32);
if (ret == -1) {
perror("listen");
return -1;
}
struct sockaddr_in client;
int len = sizeof(client);
// Open the file for writing
fp = fopen("messages.txt", "a"); // 'a' append mode
if (fp == NULL) {
perror("file open");
return -1;
}
while (1) {
int connfd = accept(tcpsocket, (struct sockaddr *)&client, &len);
if (connfd == -1) {
perror("接受");
return -1;
}
printf("客户端: IP - %s, 端口 - %d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
pthread_t thread_id;
int *pconnfd = (int *)malloc(sizeof(int));
*pconnfd = connfd;
if (pthread_create(&thread_id, NULL, handleClientConnection, (void *)pconnfd) != 0) {
perror("无法创建线程");
free(pconnfd);
close(connfd);
continue;
}
pthread_detach(thread_id);
}
close(tcpsocket);
fclose(fp); // Close the file when done
return 0;
}
原创
局域网络通信
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
评论交流
欢迎留下你的想法