
基于C的socket编程实现linux虚拟机和windows传输文件(图片)
发布日期:2021-05-15 09:23:35
浏览次数:17
分类:精选文章
本文共 3534 字,大约阅读时间需要 11 分钟。
Linux 服务端 socket 代码解读与应用实践
1.1 项目背景
本项目旨在通过 Linux 服务端 socket 实现文件传输功能,实现在客户端和服务器端之间实现数据交互。本文将详细介绍服务端的实现步骤及代码解析。
1.2 项目功能概述
服务端应当具备以下功能:
- 监听指定端口接收客户端连接
- 处理每次连接创建新的子进程
- 子进程负责接收客户端文件内容
- 将接收到的文件写入本地文件
- суб进程结束后返回处理信息
1.3 服务端代码分析
#include#include #include #include #include #include #include #define SIZE 30 void read_child(int signo) { if (signo == SIGCHLD) { int status; pid_t pid = waitpid(-1, &status, WNOHANG); printf("移除子进程挂起状态 PID=%d\n", pid); } } int main(int argc, char* argv) { int server_sock, client_sock, r; struct sockaddr_in server_addr, client_addr; pid_t pid; struct sigaction act; socklen_t len; char buf[SIZE]; if (argc != 2) { printf("需要端口号\n"); return 1; } act.sa_handler = read_child; sigemptyset(&act.sa_mask); act.sa_flags = 0; if (-1 == sigaction(SIGCHLD, &act, 0)) { printf("Sigaction 错误\n"); return -1; } server_sock = socket(AF_INET, SOCK_STREAM, 0); if (server_sock == -1) { printf("无法获取服务器 socket\n"); return -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(argv[1]); if (-1 == bind(server_sock, (struct sockaddr*)&server_addr, sizeof(server_addr))) { printf("绑定错误\n"); return -1; } if (-1 == listen(server_sock, 10)) { printf("监听错误\n"); return -1; } while (1) { len = sizeof client_addr; client_sock = accept(server_sock, (struct sockaddr*)&client_addr, &len); if (-1 == client_sock) continue; pid = fork(); if (pid == -1) { close(client_sock); continue; } else if (pid == 0) { close(server_sock); memset(buf, 0, SIZE); r = read(client_sock, buf, SIZE - 1); buf[r] = '\0'; FILE* fp = fopen(buf, "wb"); if (!fp) { return 1; } printf("打开文件成功\n"); memset(buf, 0, SIZE); while ((r = read(client_sock, buf, SIZE - 1)) > 0) { fwrite(buf, 1, r, fp); } fclose(fp); printf("写入文件成功\n"); close(client_sock); printf("连接客户端 IP: %s, 端口: %d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); return 0; } else { printf("新客户端连接 IP: %s, 端口: %d, 子进程 PID=%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), pid); close(client_sock); } } close(server_sock); return 0; }
1.4 Windows 客户端代码解读
#include#include #include #pragma comment(lib, "ws2_32.lib")#define IP "虚拟机IP地址"#define PORT 8889char filename[] = "1.jpg";int main() { WORD ver = MAKEWORD(2, 2); WSADATA dat; WSAStartup(ver, &dat); SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); sockaddr_in sin = {}; sin.sin_family = AF_INET; sin.sin_port = htons(PORT); sin.sin_addr.S_un.S_addr = inet_addr(IP); int len = sizeof(sin); int r = connect(sock, (sockaddr*)&sin, len); if (-1 == r) { printf("连接错误\n"); return -1; } send(sock, filename, strlen(filename), 0); char buf[1024] = {0}; r = recv(sock, buf, sizeof(buf), 0); buf[r] = '\0'; printf("接收到文件名称: %s\n", buf); FILE* fp; fp = fopen(filename, "rb"); if (!fp) { return 1; } len = fread(buf, 1, sizeof(buf), fp); while (len > 0) { send(sock, buf, len, 0); len = fread(buf, 1, sizeof(buf), fp); } fclose(fp); closesocket(sock); getchar(); return 0;}
2 常见问题及解决方案
-
端口号占用问题:服务器启动时使用
bind()
函数,如果端口号已占用,需切换为其他端口号。 -
接受客户端连接超时:可通过降低
listen()
函数的参数,或使用线程池管理多个连接。 -
读取文件问题:确保客户端发送的数据以二进制格式处理,避免文本编码转换问题。
3 总结思考
本项目通过 socket API 实现了跨平台文件传输功能,服务端部分采用了进程共享的方式处理多个客户端连接,Windows 客户端部分则依托 Winsock 库实现了文件传输功能。
发表评论
最新留言
第一次来,支持一个
[***.219.124.196]2025年04月11日 19时32分36秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
powerdesigner中怎么给一主键设为自增型auto_increment.
2019-03-12
import Vue from 'vue'的过程
2019-03-12
ubuntu16.04下系统配置
2019-03-12
电容的分类与用途
2019-03-12
国内有哪些比较靠谱的云服务器?
2019-03-12
小扎扎学测试笔记打卡-数据库测试mysql
2019-03-12
我的第一篇博客 2021-05-10
2019-03-12
Java中有几种基本数据类型?它们分别占多大字节?
2019-03-12
Java中基本类型的转换规则
2019-03-12
如何将字符串写入文件?
2019-03-12
Js插入元素到数组的头部 unshift
2019-03-12
ie8、ie9获取input文件大小
2019-03-12
原型模式在开源代码中的应用
2019-03-12
职责链模式在开源代码中的应用
2019-03-12
Mapper 接口方法如何与注解里的 SQL 进行绑定的?
2019-03-12
final 在 java 中的作用
2019-03-12
python安装和配置(win10)
2019-03-12
智力扣(13)——回字环
2019-03-12
重构函数(1)条件合并
2019-03-12
2020编码大赛(1)题目
2019-03-12