当前位置: 首页 > news >正文

北京市建设城乡建设委员会官方网站/北京seo运营推广

北京市建设城乡建设委员会官方网站,北京seo运营推广,全国企业信息公示官网,小白的博客 wordpressSocket文件传输1 在socket多线程实现多客户端连接服务器进行聊天的基础上,添加文件传输功能。 fix1 在server.c中添加file_info结构体,用于单独接受某次客户端发送的fileinfo信息(其中包含文件名、文件大小)修改server.c中worke…

Socket文件传输1


在socket多线程实现多客户端连接服务器进行聊天的基础上,添加文件传输功能。

fix1

  1. 在server.c中添加file_info结构体,用于单独接受某次客户端发送的fileinfo信息(其中包含文件名、文件大小)
  2. 修改server.c中worker函数,为其添加recv(fileinfo)的过程,并将文件名与文件大小进行输出。
  3. 修改client.c中命令行解析部分的内容,添加argv[3]参数filename
  4. 在client.c中添加file_info结构体,并在命令行解析后完成对fileinfo结构体的传输信息设置
  5. 在client.c中将文件信息与文件内容分开发送给服务端(如果合并发送则不便于分离)。
//1.server.c
#include "head.h"
#include "common.h"#define MAXUSER 100#define handle_error(msg) \do { perror(msg); exit(EXIT_FAILURE); } while (0)struct Data {int fd;struct sockaddr_in client;
};/* 传输文件的信息 */
struct file_info {char filename[50];ssize_t size;//传输文件大小
};void *worker(void *arg) {struct Data data = *(struct Data *)arg;//进行参数的类型转换int sockfd = data.fd;struct sockaddr_in client = data.client;//将参数进行解封装//1.文件info信息的接收struct file_info info;recv(sockfd, (void *)&info, sizeof(info), 0);printf("filename = %s filesize = %ldbyte\n", info.filename, info.size);while (1) {//2.文件内容的接收char buff[1024] = {0};ssize_t rsize = recv(sockfd, buff, sizeof(buff), 0);if (rsize > 0) {printf("<receive %ldbyte> %s:%d: \n%s\n", rsize, inet_ntoa(client.sin_addr), ntohs(client.sin_port), buff);} else {close(sockfd);break;}}printf("<server> : %s:%d has left!\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
}int main(int argc, char *argv[]) {//./a.out -p port//1.命令行解析if (argc != 3) {fprintf(stderr, "Usage : %s -p port", argv[0]);exit(1);}int opt;int port;int sockfd;while ((opt = getopt(argc, argv, "p:")) != -1) {switch (opt) {case 'p':port = atoi(optarg);break;default:fprintf(stderr, "Usage : %s -p port\n", argv[0]);exit(1);}}//2.创建socketif ((sockfd = socketCreate(port)) < 0) handle_error("socketCreate");//3.accept循环的接受客户端对server的连接pthread_t tid[MAXUSER + 5];//线程tid数组 用于解决线程竞争struct Data data[MAXUSER + 5];//文件描述符与client的结构体数组 用于解决文件描述符竞争while (1) {int newfd;//新建的文件描述符struct sockaddr_in client;//用于存放临时建立连接的客户端的信息socklen_t len = sizeof(client);if ((newfd = accept(sockfd, (struct sockaddr *)&client, &len)) < 0) handle_error("accept");printf("<accept> %s:%d: accept a client!\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));//4.多线程recv接受消息data[newfd].client = client;data[newfd].fd = newfd;//这样所使用的文件描述符 就是当前进程所打开的文件描述符中最小、未被使用的fd//创建线程进行work工作涉及传参问题:需要使用结构体将参数封装后,将结构体指针传给线程pthread_create(&tid[newfd], NULL, worker, (void *)&data[newfd]);//成功解决tid与fd竞争的问题}return 0;
}
//2.client.c
#include "head.h"
#include "common.h"#define handle_error(msg) \do { perror(msg); exit(EXIT_FAILURE); } while (0)int sockfd;struct file_info {char filename[50];ssize_t size;//文件大小
};//ctrl+c信号处理
void closeSock(int signum) {send(sockfd, "I am leaving...", 27, 0);close(sockfd);//关闭客户端文件描述符exit(0);
}int main(int argc, char *argv[]) {//./a.out ip port filenameif (argc != 4) {fprintf(stderr, "Usage : %s ip port filename\n", argv[0]);exit(1);}signal(SIGINT, closeSock);//1.建立连接connectif ((sockfd = socketConnect(argv[1], atoi(argv[2]))) < 0) handle_error("socketConnect");printf("connect sccuess!\n");//2.确定传输文件的相关信息infostruct file_info info;//确定传输的文件名strcpy(info.filename, argv[3]);//确定传输的文件大小FILE *fp = fopen(argv[3], "r");fseek(fp, 0, SEEK_END);info.size == ftell(fp);fseek(fp, 0, SEEK_SET);//将指针重新定位到文件的开始//3.send发送文件info信息send(sockfd, (void *)&info, sizeof(info), 0);//4.send发送文件内容信息while (1) {//循环发送消息char buff[1024] = {0};ssize_t size;if ((size = fread(buff, 1, 1024, fp)) == 0) break;//读不到数据则直接break循环//只要向文件描述符中写入 tcp服务就会帮助发送消息//With a zero flags argument, send is equivalent to write(2).send(sockfd, buff, /*strlen(buff)*/sizeof(buff), 0);//buff的最后一个字符没有设置为\0不可使用strlen(buff)}fclose(fp);close(sockfd);//断开连接return 0;
}

客户端将1.server.c的文件内容消息进行发送:

在这里插入图片描述

服务端成功读取到客户端发送的消息并进行输出:

在这里插入图片描述

在这里插入图片描述

基本功能大致实现。

bug

发现bug:

  1. 文件超过设置的buff大小1024,则将发送的文件分为多次发送,但是最后一次发送的剩余文件内容并没有达到1024byte字节大小,发送了多余的长度内容(一种资源的浪费)。

    在这里插入图片描述

  2. 对问题bug进行放大:如果直接发送一个200byte以内的文件,服务端会发生什么情况?测试结果如下:vim test.txt

    //test.txt
    this is a filetransfer test!
    the following are the content:
    today is good day.
    i would like to go outside for a walk.
    

    在这里插入图片描述

    在这里插入图片描述

fix2

每次发送1024buff的,最后一次发送文件剩余部分内容不足1024byte也居然占用了1024byte字节的问题:

定位问题到client.c文件中的59行send(sockfd, buff, sizeof(buff), 0);sizeof(buff)造成信息浪费。

解决方案1

  • 将buff的1023个字符设置为\0字符串结束标志,
  • 将fread部分修改为每次读入1023个字节。
  • sizeof(buff)改为strlen(buff)
buff[1023] = '\0';
if ((size = fread(buff, 1, 1023, fp)) == 0) break;//将文件数据读入到buff中 读不到数据则直接break循环
send(sockfd, buff, strlen(buff), 0);
//2.client.c修改后
#include "head.h"
#include "common.h"#define handle_error(msg) \do { perror(msg); exit(EXIT_FAILURE); } while (0)int sockfd;struct file_info {char filename[50];ssize_t size;//文件大小
};//ctrl+c信号处理
void closeSock(int signum) {send(sockfd, "I am leaving...", 27, 0);close(sockfd);//关闭客户端文件描述符exit(0);
}int main(int argc, char *argv[]) {//./a.out ip port filenameif (argc != 4) {fprintf(stderr, "Usage : %s ip port filename\n", argv[0]);exit(1);}signal(SIGINT, closeSock);//1.建立连接connectif ((sockfd = socketConnect(argv[1], atoi(argv[2]))) < 0) handle_error("socketConnect");printf("connect sccuess!\n");//2.确定传输文件的相关信息infostruct file_info info;//确定传输的文件名strcpy(info.filename, argv[3]);//确定传输的文件大小FILE *fp = fopen(argv[3], "r");fseek(fp, 0, SEEK_END);info.size = ftell(fp);fseek(fp, 0, SEEK_SET);//将指针重新定位到文件的开始//3.send发送文件info信息send(sockfd, (void *)&info, sizeof(info), 0);//4.send发送文件内容信息while (1) {//循环发送消息char buff[1024] = {0};buff[1023] = '\0';ssize_t size;if ((size = fread(buff, 1, 1023, fp)) == 0) break;//将文件数据读入到buff中 读不到数据则直接break循环//只要向文件描述符中写入 tcp服务就会帮助发送消息//With a zero flags argument, send is equivalent to write(2).send(sockfd, buff, /*strlen(buff)*/strlen(buff), 0);//buff的最后一个字符没有设置为\0不可使用strlen(buff)}fclose(fp);close(sockfd);//断开连接return 0;
}

在这里插入图片描述

正常接受到文件传输的信息:

在这里插入图片描述

被分割的buff中的最后一个buff的文件大小为809byte,没有资源浪费,bug成功解决。

在这里插入图片描述

对200byte以内的文件进行测试,server接受到的为118byte,没有出现资源浪费。

在这里插入图片描述

http://www.lbrq.cn/news/1340011.html

相关文章:

  • 淘宝上找人做网站/互联网营销师资格证
  • 个旧市做网站公司/手机百度app下载
  • wordpress 宽度/企业网站seo优化
  • 好看的网站 你明白吗/市场调研与分析
  • 360如何做网站优化/seo外包
  • 网站建设与开发做什么/seo谷歌外贸推广
  • 建立销售型网站/买链接网
  • 做买衣服的网站有哪些/做企业推广
  • 卡通网站建设/建站平台哪个好
  • 网站邮箱怎么做的/杭州seo搜索引擎优化
  • 海淀最新消息今天/网站关键词百度自然排名优化
  • 初学者做网站的软件/网站恶意点击软件
  • 购买网站模板/关键词快速排名怎么做
  • 基金网站制作/seo搜索引擎优化试题及答案
  • 网站备案有效期/代写软文费用全网天下实惠
  • 电视台网站建设/今晚比赛预测比分
  • 重庆招工招聘信息查询/seo外链购买
  • 微信小程序制作视频教程/南京百度seo
  • 东莞网站优化公司/seo文章代写平台
  • 无锡网站设计公司排名/泰安seo推广
  • 杭州 seo网站建设 网络服务/百度网首页
  • 怎样建设卡盟网站/网络营销最新案例
  • 下载专门做初中数学题的网站/千锋教育的真实性
  • 福州市建设局内部网站/网络营销方式有几种
  • 俄罗斯乌克兰战争最新消息/seo外包公司如何优化
  • wordpress无法创建数据库/北京网站优化seo
  • 石家庄关键词搜索引擎优化/win7优化教程
  • 网站建设公司上海做网站公司排名/小红书推广
  • dede 中英文网站/东莞网站建设哪家公司好
  • 品牌高端网站制作企业/黑五类广告推广
  • JS中typeof与instanceof的区别
  • Knuth‘s TwoSum Algorithm 原理详解
  • Pico+unity VR入门开发超详细笔记2025
  • 深入理解 Gin 框架的路由机制:从基础使用到核心原理
  • 解决python错误:playwright._impl._errors.TimeoutError: Timeout 30000ms exceeded.
  • 基于遗传优化的智能灌溉系统控制策略matlab仿真