TCP文件传输功能

news2025/2/3 6:55:18

实现代码

tcp.h

#ifndef _TCP_H_
#define _TCP_H_

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <strings.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <arpa/inet.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <fcntl.h>

#define ErrExit(msg) do { perror(msg); exit(0);} while(0) 
#define BACKLOG 5
#define OK '1'

typedef struct sockaddr_in Addr_in;
typedef struct sockaddr Addr;

typedef ssize_t (* DataHand_t)(int, void *, size_t, int);


void Argment(int argc, char *argv[]);
int SocketInit(char *argv[], bool flag);
int SocketDataHand(int fd, void *buf, size_t len, DataHand_t datahandle);
#endif

tcp.c

#include "tcp.h"
void Argment(int argc, char *argv[]) {
	if(argc < 2) {
		fprintf(stderr, "%s<addr><post>\n", argv[0]);
		exit(EXIT_FAILURE);
	}
}

int SocketInit(char *argv[], bool flag) {
	int fd;
	Addr_in addr;

	/*创建套接字*/
	if ( (fd = socket(AF_INET, SOCK_STREAM, 0) ) < 0){
		ErrExit("socket");
	}
	/*设置通信结构体*/
	bzero(&addr, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_port  = htons( atoi(argv[2]) );
	if (inet_aton(argv[1], &addr.sin_addr) == 0) {
		fprintf(stderr, "Invalid address\n");
		exit(EXIT_FAILURE);
	}

	if (flag == true) {
		/*发起连接请求*/
		if (connect(fd, (Addr *)&addr, sizeof(addr)) ) {
			perror("connect");
			exit(0);
		}
	} else {
		/*发起连接请求*/
		if (bind(fd, (Addr *)&addr, sizeof(addr)) ) {
			perror("connect");
			exit(0);
		}

		/*允许地址快速重用*/
		int b_reuse = 1;
		if( setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &b_reuse, sizeof(b_reuse) ) )
			perror("setsockopttsockopt");

		/*监听模式*/
		if ( listen(fd, BACKLOG))
			ErrExit("listen");
	}
	

	return fd;
} 

int SocketDataHand(int fd, void *buf, size_t len, DataHand_t datahandle) {
	int ret;
	char *str = datahandle == recv ? "recv" : "send";

	do {
		ret = datahandle(fd, buf, len, 0);
	} while (ret < 0 && errno == EINTR);
	if (ret < 0) 
		ErrExit(str);

	return ret;
}

server.c

#include "tcp.h"

int main (int argc, char *argv[]) {
	int fd, newfd;
	int ret, file_fd;
	char buf[BUFSIZ] = {};
	Addr_in addr, client_addr;
	socklen_t addrlen = sizeof(addr);

	/*检查参数*/
	Argment(argc, argv);

	/*创建套接字*/
	fd = SocketInit(argv, false);
	/*接收客户端连接*/
	do {
		newfd = accept(fd, (Addr *)&client_addr, &addrlen);
	} while( newfd < 0 && errno == EINTR) ;//如果信号导致的错误,继续执行

	/*接收文件名字*/
	ret = SocketDataHand(newfd, buf, BUFSIZ, (DataHand_t)recv);
	
	/*创建文件*/
	if ( (file_fd = open(buf, O_WRONLY|O_CREAT, 0660)) < 0) {
		ErrExit("file_fd");
	}
	buf[0] = OK;
	SocketDataHand(newfd, buf, 1, (DataHand_t)send);

	/*接受文件*/
	while (1) {
		ret = SocketDataHand(newfd, buf, BUFSIZ, (DataHand_t)recv);
		if (!ret) {
			break;
		}
		write(file_fd, buf, ret);
	}

	close(newfd);
	close(fd);
	return 0;
}

client.c

#include "tcp.h"

#define FILENAME "picture.png"
#define INFOFILE ".info"
int main (int argc, char *argv[]) {
	int fd;
	int ret, file_fd;
	char buf[BUFSIZ];
	FILE *fp;
	char *filename = argv[1];
	/*检查参数*/
	if(argc < 2) {
		printf("%s<filename>\n", argv[0]);
		exit(0);
	}

	/*通过配置文件获取IP地址和端口号*/
	if ( (fp = fopen(INFOFILE, "r"))  < 0) 
		ErrExit("fopen");
	
	fgets(buf, 20, fp);
	buf[strlen(buf)-1] = '\0';
	argv[1] = buf;
	fgets(&buf[20], 20, fp);
	buf[strlen(&buf[20])-1 + 20] = '\0';
	argv[2] = &buf[20];

	/*创建套接字*/
	fd = SocketInit(argv, true);

	/*打开文件*/
	if ( (file_fd = open(filename, O_RDONLY)) < 0 ) {
		ErrExit("open");
	}
	/*发送文件名*/
	SocketDataHand(fd, filename, strlen(filename), (DataHand_t) send);
	SocketDataHand(fd, buf, 1, recv);

	/*发送文件*/
	if (buf[0] == OK) {
		while (1) {
			do {
				ret = read(file_fd, buf, BUFSIZ);
			} while (ret < 0 && errno == EINTR);
			if(ret < 0) 
				ErrExit("read");
			if(!ret)
				break;
			ret = SocketDataHand(fd, buf, ret, (DataHand_t) send);
			if(!ret)
				break;
		}
	}
	printf("flie success\n");
	close(file_fd);
	close(fd);
	return 0;
}

.info

127.0.0.1
8888

通过以上代码就可以实现用文件名称来传输文件了
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/762260.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

链表的简单示意

链表的实质就是指针。存放下一个元素的地址。 typedef struct spy {char * name ;struct spy * next; }spy ,*p_spy;spy A {A,NULL}; spy B {B,NULL}; spy C {C,NULL};int main() {p_spy &A;A.next&B;//A是一个结构体变量&#xff0c;A.next是对这个结构体变量的引用。…

MySQL八股学习记录4事务的实现from小林coding

MySQL八股学习记录4事务的实现from小林coding 事务的概念与特性并行事务引发的问题脏读不可重复读幻读 MySQL的应对策略InnoDB引擎可重复读详解ReadView在MVCC中的工作方式两种隔离级别通过MVCC实现幻读被完全解决了吗 事务的概念与特性 概念:一个操作要么执行成功,要么回滚到…

Matplotlib subplots()函数详解

matplotlib.pyplot模块提供了一个 subplots() 函数&#xff0c;它的使用方法和 subplot() 函数类似。其不同之处在于&#xff0c;subplots() 既创建了一个包含子图区域的画布&#xff0c;又创建了一个 figure 图形对象&#xff0c;而 subplot() 只是创建一个包含子图区域的画布…

面试题揭秘:Spring Boot 自动配置原理是什么?

大家好&#xff0c;我是你们的小米。在过去的几年里&#xff0c;Spring Boot已经成为了Java开发领域中最受欢迎的框架之一。它以其简化的开发方式和强大的功能而闻名于世。今天&#xff0c;我们来揭秘一个常见的面试题&#xff1a;Spring Boot自动配置原理是什么&#xff1f;让…

针对汽配企业的生产难点,提出MES管理系统解决方案

随着汽车产业的快速发展&#xff0c;汽配企业面临着越来越多的生产难点&#xff0c;如生产过程不透明、效率低下、质量控制困难等。为了应对这些挑战&#xff0c;引入MES生产管理系统成为了一种有效的解决方案。本文将探讨MES生产管理系统在汽配企业中的应用&#xff0c;以及它…

【江西省研究生数学建模竞赛】第一题 蒸汽发生器倒U型管内液体流动 70页论文及MATLAB代码

【江西省研究生数学建模竞赛】题目之一 蒸汽发生器倒U型管内液体流动 70页论文及MATLAB代码 相关链接 【江西省研究生数学建模竞赛】第一题 蒸汽发生器倒U型管内液体流动 70页论文及MATLAB代码 【江西省研究生数学建模竞赛】第一题 蒸汽发生器倒U型管内液体流动 70页论文及MA…

如何顺势而为,让ChatGPT为教育所用?

恐惧和回避无法阻挡科技的浪潮&#xff0c;教育与AI的深度融合时代已经到来&#xff0c;如何把AI当做工具&#xff0c;把其成为教育的机会而非威胁&#xff0c;是教育体系未来不得不得面对的新变化。 接受ChatGPT作为一种教学辅助工具&#xff0c;成为教师的朋友或者帮手&…

备战秋招010(20230717)

文章目录 前言一、基础1、网络模型01、OSI 七层02、TCP/IP 四层04、Linux 网络协议栈05、问题 2、常见的网络协议01、应用层02、传输层03、网络层 3、输入网址到网页显示过程01、基础02、DNS 解析03、URL 和 URI 二、HTTP1、基础01、概念02、状态码03、无状态 2、Get 和 Post01…

element-ui select数据回显显示数字的问题 el-select校验失效出现阿拉伯数字问题

初始化参数 return {fields: [{"title":"景区","id":0},{"title":"酒店","id":1}],evaluates: [{"title":"好评","id":0},{"title":"中评","id":1…

【Linux】- Linux 磁盘分区、挂载

Linux 磁盘分区、挂载 1.1 Linux 分区1.2 硬盘说明1.3 磁盘情况查询 1.1 Linux 分区 原理介绍 Linux 来说无论有几个分区&#xff0c;分给哪一目录使用&#xff0c;它归根结底就只有一个根目录&#xff0c;一个独立且唯一的文件结构 , Linux 中每个分区都是用来组成整个文件系…

SAP AES encrypt

加密算法简介: 加密技术通常分为两大类:"对称式"和"非对称式"。 对称性加密算法&#xff1a;对称式加密就是加密和解密使用同一个密钥。信息接收双方都需事先知道密匙和加解密算法且其密匙是相同的&#xff0c;之后便是对数据进行加解密了。对称加密算法…

【近场社交项目】数据库系统期末设计——逻辑设计部分

【近场社交项目】数据库系统期末设计——逻辑设计部分&#x1f60e; 前言&#x1f64c;3.2逻辑设计1、各个表的二维表&#xff1a;2. 用户信息ER图转换为逻辑和关系模型&#xff1a;3. 用户进行下单业务的ER图转换为逻辑关系模型4. 用户充值会员业务ER图转换为逻辑关系模型5. 用…

springboot实现全局异常捕获

导言&#xff1a; 为什么要做异常处理&#xff1a; 原因有三&#xff1a; 1、将系统产生的全部异常统一捕获处理。 2、自定义异常需要由全局异常来捕获。 3、JSR303规范的validator参数校验器、参数校验不通过、本身无法使用try…catch 其实对于前后端分离的项目做异常处理…

ROS:导航功能详解

目录 一、导航简介1.1导航概念1.2导航作用1.3导航模块简介1.3.1全局地图1.3.2自身定位1.3.3路径规划1.3.4运动控制1.3.5环境感知 1.4导航条件1.4.1硬件1.4.2软件 二、坐标系2.1坐标系简介2.2坐标系特点2.3坐标系变换 三、导航功能实现3.1SLAM建图3.1.1gmapping简介3.1.2gmappin…

【VUE】解决VU2项目图片视频加载缓慢/首屏加载白屏的问题

1 问题描述 前端项目中&#xff0c;有时候会出现图片视频加载缓慢、首屏加载白屏的问题 之前写了一篇在VU3项目中的解决方案&#xff0c; 现在讲一下在 Vue2 项目中的解决方法&#xff0c;方法思路都差不多&#xff0c;在代码示例上会有一些小差别 2 原因分析 通常是由以下原因…

辅助驾驶功能开发-功能规范篇(22)-6-L2级辅助驾驶方案功能规范

1.3.6 ELK 系统功能定义 ELK全称Emergency Lane Keeping&#xff0c;即紧急车道保持。当车辆与道路边界护栏&#xff08;包含隔离带护栏、路锥、水马&#xff09; 有碰撞危险或当车辆正偏出道路边沿且存在“对向来车”或“后向来车”与本车有碰撞风险时&#xff0c;通过给与转向…

Redis源码篇- SDS

Redis对于String类型&#xff0c;底层使用的是SDS&#xff08;简单动态字符串&#xff09;&#xff0c;而不是常规的C语言的字符数组 。 通常在C中&#xff0c;定义一个字符串&#xff0c;方式是通过字符数组表示&#xff0c;同时结尾使用/0表示结束&#xff1a;char [] &quo…

C语言 与 C++ 通讯录对比实现(附带源码)

目录 1.通讯录的基本框架 C语言版 C版 2.增加联系人 C语言版 C版 3.删除联系人 C语言版 C版 4.查找与打印联系人 C语言版 C版 5.修改联系人 C语言版 C版 6.排序联系人 C语言版 C版 7.其他 8.总结 本文章将对C语言、C版本的通讯录进行对比实现。其中C版本引入大量C语言没有的特性…

第 5 章 Spark Shuffle 解析

第 5 章 Spark Shuffle 解析 5.1 Shuffle 的核心要点1. 数据分区&#xff1a;2.数据传输&#xff1a;3. 数据排序&#xff1a;4.数据聚合&#xff1a;5. 数据重分发&#xff1a;6.数据持久化&#xff1a;5.1.1 ShuffleMapStage 与 ResultStage 5.2 HashShuffle 解析5.2.1 未优化…

KUKA机器人_外部安全条件不满足时,如何操作机器人的方法

KUKA机器人_外部安全条件不满足时&#xff0c;如何操作机器人的方法 如果大家在做项目时&#xff0c;控制系统尚未完成&#xff0c;外部紧急停止等安全条件尚未满足时&#xff0c;但是此时想操作或移动机器人&#xff0c;有办法吗&#xff1f; 答案是有。 具体的方法可参考以…