首页 > 其他分享 >TCP 实现跨平台文件传输

TCP 实现跨平台文件传输

时间:2022-12-20 17:36:11浏览次数:38  
标签:serv addr BUFFSIZE 文件传输 TCP filename 跨平台 fd printf


TCP 实现跨平台文件传输

实验目的

利用 TCP 完成 linux 和 windows 平台的文件传输。

实验原理

windows 与 linux 上实现 tcp 文件传输本质上是相同的,只有一些函数调用方式不一样, 这里我们仍使用上个实验的服务器端,重点学习 windows 下套接字编写。

实验步骤

1.服务器

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

#define PORT 11111 // 设置端口号
#define LISTENQ 10 // 设置监听队列长度
#define BUFFSIZE 1024 // 设置缓冲区大小
#define FILE_BUFFSIZE 100 // 设置文件缓冲区大小
#define END_FLAG "end" // 结束标记

int passiveTCP() {//封装 tcp 的建立
// 创建套接字,使用流数据格式
int serv_fd = socket(AF_INET, SOCK_STREAM, 0);
// 定义一个地址结构体变量
struct sockaddr_in serv_addr;
// 清零地址
memset(&serv_addr, 0, sizeof(serv_addr));

// 给地址结构体设置值
serv_addr.sin_family = AF_INET; // Ipv4
serv_addr.sin_port = htons(PORT); // 指定端口号
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 指定任意ip
bind(serv_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); // 套接字绑定地址结构
listen(serv_fd, LISTENQ); // 设置为监听模式
return serv_fd; // 返回套接字
}


int main() {
int serv_fd = passiveTCP(); // 创建套接字并绑定端口和ip
char filename[FILE_BUFFSIZE];
char buffer[BUFFSIZE];
int cnt = 0;

while (1) {
//将文件接收到服务器根目录
int clie_fd;
// 定义一个新的地址结构变量
struct sockaddr_in clie_addr;
// 清零地址结构
memset(&clie_addr, 0, sizeof(clie_addr));

int len = sizeof(clie_addr);
// 处理连接请求, 返回一个新的套接字,用户客户端通信
printf("初始化成功\n");
if ((clie_fd = accept(serv_fd, (struct sockaddr *)&clie_addr, &len)) < 0) {
printf("error\n");
}
else {
char buff_t[BUFFSIZE] = { 0 }; //做中间临时保存
cnt ++;
printf("===connect success %d===\n", cnt);
// 处理考虑有多个文件的情况
while(1){
memset(filename, 0, FILE_BUFFSIZE);
memset(buffer, 0, BUFFSIZE);
recv(clie_fd, filename, sizeof(filename), 0);//接收文件名

if( strcmp(filename, END_FLAG) == 0 || strcmp(filename, "") == 0){
break; // 文件全部发送完毕
}

printf("#> %s\n", filename);
// 对文件名进行处理
int t = (int)(strchr(filename, '.') - filename); // 计算'.'的下标
// 判断文件有无后缀
if( t < 0 )
{
strcat(filename, "_副本");
printf("#> save filename: [%s]\n", filename);
}
else{
// 将后缀保存
strcpy(buff_t, filename + t);
printf("#> %s\n", buff_t);
strcpy(filename + t, "_副本");
printf("#> %s\n", filename);
strcat(filename, buff_t);
printf("#> save filename: [%s]\n", filename);
}
FILE *fp = fopen(filename, "w");//创建文件
printf("transport start\n");
int n;
// 接收文件内容,并写入打开的文件中,直到文件结尾
while ((n = recv(clie_fd, buffer, BUFFSIZE, 0)) > 0) {
//printf("%d: %s\n", strlen(buffer), buffer);
if( strcmp(buffer, END_FLAG) == 0){
break;
}
fwrite(buffer, sizeof(char), n, fp);
// buffer 清零
memset(buffer, 0, BUFFSIZE);
}
printf("transport finish\n");
printf("_______________________\n");
// 关闭文件
fclose(fp);
}
// 关闭连接新建套接字
close(clie_fd);
printf("===connect close %d===\n", cnt);
}
}
// 关闭服务器套接字
close(serv_fd);

return 0;
}

2.客户端

#define _CRT_SECURE_NO_WARNINGS // vs 使用scanf()
#pragma comment(lib, "ws2_32.lib") //加载 ws2_32.dll
#include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h>
#define IP "10.13.146.222" // 指定服务器ip
#define PORT 11111 // 指定端口号
#define BUFFSIZE 1024 // 缓冲区大小
#define FILE_BUFFSIZE 100 // 文件名大小
#define END_FLAG "end"
int passiveTCP()
{
//初始化 DLL
WSADATA wsadata;
//WSAStartup()函数对 Winsock DLL 进行初始化
if (WSAStartup(MAKEWORD(2, 0), &wsadata) == SOCKET_ERROR){
printf("Socket initialize fail!\n");
return -1;
}
else{
printf("Socket initialize success!\n");
}
// //创建套接字
SOCKET sock;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR){
printf("Socket create fail!\n");
return -1;
}
else{
printf("Socket create success!\n");
}
//绑定套接字
struct sockaddr_in ClientAddr;
// 每个字节都用0填充
memset(&ClientAddr, 0, sizeof(ClientAddr));
ClientAddr.sin_family = AF_INET;
ClientAddr.sin_port = htons(PORT);
ClientAddr.sin_addr.s_addr = inet_addr(IP);
// 向服务器发起请求
system("request_.vbs");
if (connect(sock, (LPSOCKADDR)&ClientAddr, sizeof(ClientAddr)) == SOCKET_ERROR){
//system("seccess_no.vbs");
printf("Connect fail!\n");
closesocket(sock);
return -1;
}
else{
//system("seccess_.vbs");
printf("Connect success!\n");
}
return sock; // 返回套接字
}
int main()
{
SOCKET serv_fd = passiveTCP();
if (serv_fd == -1){
char c;
while (serv_fd == -1){
printf("是否重连(y/n):");
fflush(stdin);
scanf("%c", &c);
if (c == 'y'){
serv_fd = passiveTCP();
}
else{
return 0; // 连接失败,没有找到服务器
}
}

}
char buffer[BUFFSIZE];
char filename[FILE_BUFFSIZE];
memset(buffer, 0, BUFFSIZE);
memset(filename, 0, FILE_BUFFSIZE);
//system("file_.vbs");
/*printf("input filename:");
scanf("%s", filename);*/
int cnt = 0;
char file_name_t[FILE_BUFFSIZE][FILE_BUFFSIZE];
printf("input filename:");
fflush(stdin); // 清空缓冲区
fgets(filename, FILE_BUFFSIZE, stdin); // 输入遇到回车结束
// 将字符串最后的'\n'去掉
filename[strlen(filename) - 1] = '\0';
// 分割字符串
char *p = strtok(filename, " ");
while (p){
//printf("&> %s\n", p);
strcpy(file_name_t[cnt++], p);
p = strtok(NULL, " ");
}
for (int i = 0; i < cnt; i++){
if (strcmp(file_name_t[i], "") == 0){
continue;
}
FILE* fp = fopen(file_name_t[i], "r"); // 以读的方式打开文件
if (fp == NULL) {
printf("%s :file not exist\n", file_name_t[i]);
printf("$> %s\n\n", END_FLAG);
continue;
}
else {
//先传送文件名,后传送文件内容
printf("transport start\n");
send(serv_fd, file_name_t[i], sizeof(file_name_t[i]), 0);
printf("$> %s\n", file_name_t[i]);
int n;
// 读取文件的内容并发送,直到文件发送内容发送完毕
while ((n = fread(buffer, sizeof(char), BUFFSIZE, fp)) > 0) {
send(serv_fd, buffer, n, 0);
// printf("%s\n", buffer);
// 发送完后将buffer清零
memset(buffer, 0, sizeof(buffer));
}
printf("transport finish\n");
Sleep(10);
send(serv_fd, END_FLAG, sizeof(END_FLAG), 0); // 发送结束标志
printf("$> %s\n\n", END_FLAG);
}
// 关闭文件
fclose(fp);
Sleep(10);
}
closesocket(serv_fd);
WSACleanup();//终止对 Winsock DLL 的使用,并释放资源,以备下一次使用
return 0;
}

实验结果

传输前 windows 端客户端根目录下有wct.txt, speak.c,Linux 端服务器根目录下没有这些文件

TCP 实现跨平台文件传输_网络

TCP 实现跨平台文件传输_linux_02

TCP 实现跨平台文件传输_#define_03

TCP 实现跨平台文件传输_socket_04

传输完成后我们发现服务器根目录下出现了 wct_副本.txt, speak_副本.c,并且内容和客户端根目录下的文件相同,传 输成功

TCP 实现跨平台文件传输_socket_05


标签:serv,addr,BUFFSIZE,文件传输,TCP,filename,跨平台,fd,printf
From: https://blog.51cto.com/u_15918664/5956351

相关文章

  • 利用 TCP 完成文件传输的设计
    利用TCP完成文件传输的设计实验目的输入文件路径,利用TCP实现客户文件向服务器的传输,并实现对TCP的基本封装实验原理1.服务器(1)建立socket(2)确定服务器scokaddr_i......
  • TCP那些你需要掌握的知识
    什么是TCP/IP?TCP/IP协议模型(TransmissionControlProtocol/InternetProtocol),包含了一系列构成互联网基础的网络协议,是Internet的核心协议。并不只有TCP与IP两种协......
  • 微软发现跨平台僵尸网络:对Minecraft服务器发起DDoS攻击!
    微软周四标记了一个跨平台僵尸网络,该僵尸网络主要用于对私人Minecraft服务器发起分布式拒绝服务(DDoS)攻击。该僵尸网络称为MCCrash,其特点是具有独特的传播机制,允许其传播到......
  • 不要启用 net.ipv4.tcp_tw_recycle
    本文为翻译英文BLOG《​​CopingwiththeTCPTIME-WAITstateonbusyLinuxservers​​》,但并非完整的翻译,译者CFC4N对原文理解后,进行了调整,增加了相关论点论据,跟原文稍......
  • TCP/IP 协议(10):TCP 协议一百问
    TCP/IP协议(10):TCP协议一百问​​杨领well的TCP/IP协议专栏​​TCP协议部分一直没有更新,是因为我不确定到底应该怎么来介绍TCP协议才能干货满满。最后我决定以Q&A......
  • Kodi v20 "Nexus" RC1 发布,开源跨平台媒体播放器
    Kodiv20"Nexus"RC1发布,开源跨平台媒体播放器来源:OSCHINA编辑: 局2022-12-1907:36:00 0Kodi是由XBMC基金会开发的开源媒体播放器,原名XBMC(最后......
  • TCPIP命令总结
    TCPIP命令总结1、网络设备的几种模式?1)用户模式刚刚进入就是用户模式2)特权模式执行:enable或者en3)全局模式执行:config terminal或者conf t4)接口模式interface f0/0  ......
  • DNS用的是TCP协议还是UDP协议
    DNS占用53号端口,同时使用TCP和UDP协议。那么DNS在什么情况下使用这两种协议?DNS在区域传输的时候使用TCP协议,其他时候使用UDP协议。(一)TCP与UDP简介TCP---传输控制协议,是......
  • TCP协议
    一、TCP协议介绍TCP(TransmissionControlProtocol,传输控制协议/网际协议),也叫网络通讯协议,是指能够在多个不同网络间实现信息传输的协议簇。TCP/IP协议不仅仅指的是TC......
  • 微软跨平台maui开发chatgpt客户端
    image什么是maui.NET多平台应用UI(.NETMAUI)是一个跨平台框架,用于使用C#和XAML创建本机移动(ios,andriod)和桌面(windows,mac)应用。imagechagpt最近......