c语言 网络编程实现 群聊 私聊 上传下载文件 代码
时间: 2024-05-06 15:18:22 浏览: 83
上传下载文件—C写的源码
5星 · 资源好评率100%
以下是一个简单的 C 语言网络编程实现的群聊、私聊、上传下载文件的示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#define MAX_CLIENT_NUM 10
#define BUFFER_SIZE 1024
int client_sockfd[MAX_CLIENT_NUM]; // 所有客户端的 sockfd
int client_num = 0; // 当前连接的客户端数量
// 群聊函数
void send_to_all_clients(char *msg, int len)
{
for (int i = 0; i < client_num; i++)
{
// 发送给所有客户端
write(client_sockfd[i], msg, len);
}
}
// 私聊函数
void send_to_client(int sockfd, char *msg, int len)
{
int i;
for (i = 0; i < client_num; i++)
{
// 找到对应的客户端
if (client_sockfd[i] == sockfd)
{
break;
}
}
if (i == client_num)
{
printf("Error: client %d not found\n", sockfd);
return;
}
// 向指定客户端发送消息
write(client_sockfd[i], msg, len);
}
// 线程函数,接收客户端消息并处理
void *handle_client(void *arg)
{
int sockfd = *(int *)arg;
char buffer[BUFFER_SIZE];
while (1)
{
memset(buffer, 0, sizeof(buffer));
int len = read(sockfd, buffer, BUFFER_SIZE); // 接收消息
if (len == 0) // 客户端断开连接
{
printf("Client %d disconnected\n", sockfd);
close(sockfd);
for (int i = 0; i < client_num; i++)
{
if (client_sockfd[i] == sockfd)
{
// 移除客户端
client_num--;
for (int j = i; j < client_num; j++)
{
client_sockfd[j] = client_sockfd[j+1];
}
break;
}
}
pthread_exit(NULL);
}
else if (strcmp(buffer, "quit\n") == 0) // 客户端主动退出
{
printf("Client %d quit\n", sockfd);
close(sockfd);
for (int i = 0; i < client_num; i++)
{
if (client_sockfd[i] == sockfd)
{
// 移除客户端
client_num--;
for (int j = i; j < client_num; j++)
{
client_sockfd[j] = client_sockfd[j+1];
}
break;
}
}
pthread_exit(NULL);
}
else if (strncmp(buffer, "to ", 3) == 0) // 私聊消息
{
char *ptr = strchr(buffer, ' ');
if (ptr == NULL)
{
printf("Error: invalid message format\n");
}
else
{
int len1 = ptr - buffer - 3;
int len2 = len - len1 - 3;
char name[20];
strncpy(name, buffer+3, len1);
name[len1] = '\0';
printf("Private message to %s: %s", name, ptr+1);
send_to_client(sockfd, ptr+1, len2);
}
}
else if (strncmp(buffer, "file ", 5) == 0) // 上传文件
{
char *ptr = strchr(buffer, ' ');
if (ptr == NULL)
{
printf("Error: invalid message format\n");
}
else
{
char name[20];
strncpy(name, ptr+1, len-6);
name[len-6] = '\0';
printf("File '%s' received from client %d\n", name, sockfd);
char filename[50];
sprintf(filename, "recv/%s", name);
FILE *fp = fopen(filename, "wb");
if (fp == NULL)
{
printf("Error: failed to create file\n");
}
else
{
while (1)
{
memset(buffer, 0, sizeof(buffer));
int len = read(sockfd, buffer, BUFFER_SIZE);
if (len <= 0)
{
break;
}
fwrite(buffer, 1, len, fp);
if (len < BUFFER_SIZE)
{
break;
}
}
fclose(fp);
printf("File '%s' saved as '%s'\n", name, filename);
}
}
}
else // 群聊消息
{
printf("Message from client %d: %s", sockfd, buffer);
send_to_all_clients(buffer, len);
}
}
}
int main(int argc, char *argv[])
{
int server_sockfd, client_sockfd;
struct sockaddr_in server_addr, client_addr;
int port = 12345;
// 创建套接字
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (server_sockfd < 0)
{
perror("socket");
exit(1);
}
// 绑定端口
memset(&server_addr, 0, sizeof(server_addr));
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)) < 0)
{
perror("bind");
exit(1);
}
// 监听端口
if (listen(server_sockfd, MAX_CLIENT_NUM) < 0)
{
perror("listen");
exit(1);
}
printf("Server started, listening on port %d\n", port);
while (1)
{
socklen_t client_len = sizeof(client_addr);
// 接受连接请求
client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_addr, &client_len);
if (client_sockfd < 0)
{
perror("accept");
continue;
}
if (client_num >= MAX_CLIENT_NUM) // 客户端数量达到上限
{
printf("Error: too many clients\n");
close(client_sockfd);
continue;
}
client_sockfd[client_num] = client_sockfd;
client_num++;
printf("Client %d connected\n", client_sockfd);
pthread_t tid;
pthread_create(&tid, NULL, handle_client, &client_sockfd);
}
return 0;
}
```
注:以上代码仅供参考,实际应用中需要根据具体情况进行修改。例如,文件上传下载功能还需要考虑文件重名、文件不存在等情况。
阅读全文