C语言socket实现文件下载[通俗易懂]

C语言socket实现文件下载[通俗易懂]是网络编程的作业,我比较菜。。。写到定位输出,做百分比出现了问题,不显示0到100的,直接从0跳到了100。请教了下大佬。改了过来。原来是类型的问题,做出来的运算应该是float,但是我都定义的int,输出也是,大佬指出后,我好尴尬。。。犯了小错误。。。但是在这次过程也学习了一波。要加油了!!!代码写的这么乱!!!写的是带颜色的版本,,颜色有可能会觉得妖艳,,,好吧。编译平台是vc++6.0

大家好,又见面了,我是你们的朋友全栈君。

是网络编程的作业,我比较菜。。。写到定位输出,做百分比出现了问题,不显示0到100的,直接从0跳到了100。请教了下大佬。改了过来。原来是类型的问题,做出来的运算应该是float,但是我都定义的int,输出也是,大佬指出后,我好尴尬。。。犯了小错误。。。但是在这次过程也学习了一波。要加油了!!!代码写的这么乱!!!
写的是带颜色的版本,,颜色有可能会觉得妖艳,,,好吧。
编译平台是vc++6.0

还是有点bug,有时,客户端发dir命令时会退出。有空再看看。这几天太忙。。。萌新的我只会点C,不会C++。。。如有错误,望大佬指出。谢谢。
自己试了下,发现了错误。目录错了!之前因为我两个目录都有要下载的文件。。。改成\..\,让他下载的目录返回上一级就好了。又出现了错误,原来拿编译器运行显示的目录和直接exe运行的是不同的。。。。。而且直接exe运行也不会出现dir退出的现象。研究研究

若要实现返回dos中dir命令的效果只需改成
system("dir>allfiles.txt");

sever:


#include<winsock2.h>
#include<windows.h>
#include<stdio.h>
#include<Ws2tcpip.h>
#include<iostream>
#include<fstream>
#include <direct.h>
#pragma comment(lib,"Ws2_32.lib")
using namespace std;
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT 8088
#define BUFFER_SIZE 4096
char    SendBuffer[BUFFER_SIZE],RecvBuffer[BUFFER_SIZE];   //发送缓冲区及接收缓冲区
SOCKET          AcceptSocket;
DWORD WINAPI ClientThread(LPVOID lp);
struct CLIENTINFO{
SOCKET          clientsocket;
sockaddr_in     sockaddr;
};
int main(int argc, TCHAR* argv[])
{
int         Ret;
WSADATA     wsaData;
if((Ret = WSAStartup(MAKEWORD(2,2),&wsaData)) != NO_ERROR)
{
printf("WSAStartup failed with error %d\n",Ret);
return -1;
}//if
// Create a new socket to listening for client connections.
SOCKET      ListenSocket;
if((ListenSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) 
== INVALID_SOCKET)
{
printf("socket failed with error %d\n",WSAGetLastError());
WSACleanup();
return -1;
}//if
sockaddr_in     service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("127.0.0.1");
service.sin_port = htons(DEFAULT_PORT);
if(bind(ListenSocket,(SOCKADDR* ) &service,sizeof(service)) == SOCKET_ERROR)
{
printf("bind failed with error %d\n",WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return -1;
}//if
if(listen(ListenSocket, 10) == SOCKET_ERROR)
{
printf("Error listening on socket.\n");
closesocket(ListenSocket);
WSACleanup();
return -1;
}//if
SOCKET          AcceptSocket;
sockaddr_in     ClientAddr;//接收客户端地址
int     addrClientlen = sizeof(ClientAddr);
while(true)
{
CLIENTINFO      clientInfo;
printf("waiting for client to connect......\n");
AcceptSocket = accept(ListenSocket,(sockaddr* ) &ClientAddr, &addrClientlen);
if(AcceptSocket == INVALID_SOCKET)
{
printf("accept failed : %d\n",WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}//if
clientInfo.clientsocket = AcceptSocket;
memcpy(&clientInfo.sockaddr,&ClientAddr,sizeof(sockaddr_in));
printf("a client is coming......\n");
DWORD dwThreadID;
CreateThread(NULL,0,ClientThread,(LPVOID* )&clientInfo,0,&dwThreadID);
}//while
closesocket(ListenSocket);
WSACleanup();
return 0;
} //main
DWORD WINAPI ClientThread(LPVOID lp)
{
CLIENTINFO *pClientInfo = (CLIENTINFO* )lp;
SOCKET  clientsocket = pClientInfo->clientsocket;
sockaddr_in sockaddr;
memcpy(&sockaddr,&pClientInfo->sockaddr,sizeof(sockaddr_in));
int     iResult,bytes;
char    recvRFileName[DEFAULT_BUFLEN] = "";
char    temp_buffer[BUFFER_SIZE];
unsigned readlen;
DWORD dwReadSize = 0;
char   curPath[MAX_PATH]; 
char quit [10] ="quit";
//获得相对路径
GetModuleFileName(NULL,(LPSTR)curPath,sizeof(curPath));
strrchr( curPath, '\\')[0]= 0;
ifstream infile;
while(true)
{
memset(recvRFileName,0,sizeof(recvRFileName));
iResult = recv(clientsocket,recvRFileName,DEFAULT_BUFLEN,0);
if(SOCKET_ERROR == iResult)
{
printf("recvieve failed with error : %d\n",WSAGetLastError());
closesocket(clientsocket);
WSACleanup();
return -1;
}//if
//命令有get help exit -s(文件大小)
//help
char dir [10] ="dir";
char get [10] ="get";
printf("传过来的数据:%s",recvRFileName);
if(strcmp(recvRFileName,dir)==0){
//返回命令
system("cmd /c dir /a-d /b >allfiles.txt");
printf("查看allfiles文件\n");
//将打印出来的文件信息读取出来
FILE *file;
char buf[1024];
int len=0,i=0;
char *array[1024];
char filedir [1024];//要传过去的文件目录
file=fopen("allfiles.txt","r");//打开TXST.TxT文件
if(!file)return -1;
while(fgets(buf,1024,file))//读取TXT中字符
{
len=strlen(buf);
array[i]=(char*)malloc(len+1);
if(!array[i])break;
strcpy(array[i++],buf);
}//while
fclose(file);
i--;
while(i>=0&&array[i])
{
printf("%s\n",array[i]);//打印test文档的字符
iResult = send(clientsocket,array[i],strlen(array[i]),0);
if(iResult==SOCKET_ERROR){
printf("发送失败\n");}
free(array[i--]);
}//while
printf("发送结束quit\n");
send(clientsocket,quit,strlen(quit),0);
continue;
}//if
//完整文件名
strcat(curPath,"\\");
strcat(curPath,recvRFileName);
strcpy( recvRFileName,curPath);
//获取文件大小
FILE * pFile;
long size;
pFile = fopen (recvRFileName,"rb");
if (pFile==NULL)
perror ("Error opening file");
else
{
fseek (pFile, 0, SEEK_END);   ///将文件指针移动文件结尾
size=ftell (pFile); ///求出当前文件指针距离文件开始的字节数
fclose (pFile);
printf ("FileSize : %ld bytes.\n",size);
char a[30];
//将size保存在字符串a中
sprintf(a,"%d",size);
send(clientsocket, a, 30, 0);
printf("发送文件大小:%s",a);
}
printf("文件:%s\n",recvRFileName);
infile.open(recvRFileName,ios::in|ios::binary);
if(!infile)
{    //未成功打开文件
printf("Sorry, cannot open %s. Please try again.\r\n",recvRFileName);
//break;
}//if
else
{
printf("The file %s is found,ready to transfer.\n",recvRFileName);
printf("Transfering\r\n"); 
while (!infile.eof())
{    //循环读取文件并通过h_NewSocket发送到客户端
//printf(SendBuffer,"%s",temp_buffer); 
infile.read(SendBuffer,BUFFER_SIZE);
readlen = infile.gcount();
send(clientsocket, SendBuffer, readlen, 0);
//printf("."); 
}
infile.close();
printf("Transfer completed... \r\n"); 
//bytes = send(AcceptSocket, SendBuffer, strlen(SendBuffer), 0);
}//else 
//如果没有数据发送
iResult = shutdown(clientsocket,SD_BOTH);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed: %d\n", WSAGetLastError());
}//if
closesocket(clientsocket);
return 0;
}//while
}//main

client:


#include<winsock2.h>
#include<windows.h>
#include<Ws2tcpip.h>
#include<stdio.h>
#include<string>
#include<iostream>
#include<fstream>
using namespace std;
#pragma comment(lib,"Ws2_32.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT 5150
#define BUFFER_SIZE 4096
int main(int argc, TCHAR* argv[])
{
int         iResult,rec;
WSADATA     wsaData;
HANDLE hout;
ofstream    outfile;
SOCKET ConnectSocket = INVALID_SOCKET;
struct sockaddr_in clientService;
char    sendbuf[DEFAULT_BUFLEN] = "";
char    szBuffer[BUFFER_SIZE];
BOOL    issend = true;
//初始化Windows Sockets DLL
if(iResult = WSAStartup(MAKEWORD(2,2),&wsaData) != NO_ERROR)
{
printf("WSAStartup failed with error : %d\n",iResult);
return -1;
}
//创建socket
ConnectSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(ConnectSocket == INVALID_SOCKET)
{
printf("socket failed with error : %d\n",WSAGetLastError());
WSACleanup();
return -1;
}

char addr[20];
int prot ;
printf("现在运行的是客户端!\n");
printf("**************************************************************\n");
printf("请输入服务器的IP地址:");
scanf("%s",addr);
printf("请输入服务器的端口:");
scanf("%d",&prot);
///
//设置目的网络地址并连接服务器
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr(addr);
clientService.sin_port = htons(prot);
iResult = connect(ConnectSocket,(SOCKADDR* )&clientService,sizeof(clientService));
if(iResult == SOCKET_ERROR)
{
printf("connect failed with error : %d\n",WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return -1;
}
printf("connect with server successfully!!!\n");
hout = GetStdHandle(STD_OUTPUT_HANDLE);  
SetConsoleTextAttribute(hout,  
FOREGROUND_GREEN);   
cout<<"输入命令:******************* help 获取命令提示**********************:\n";
while(true)
{
//输入命令:
char cmd [20];
char help [10] ="help";
char exit [10] ="exit";
char get [10] ="get";
char dir [10] ="dir";
char quit [10] ="quit";
scanf("%s",&cmd);
printf("输入的命令是%s\n",cmd);
if(strcmp(cmd,help)==0){
printf("命令参数:\n help----------获取命令帮助\n dir----------获取文件目录\n get----------下载文件\n exit----------退出\n");
continue;
}
// 列目录
if(strcmp(cmd,dir)==0){
iResult = send(ConnectSocket,dir,strlen(dir),0);
if(SOCKET_ERROR == iResult)
{
printf("send failed with error : %d\n",WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return -1;
}
//接收传过来的目录
SetConsoleTextAttribute(hout,  
FOREGROUND_GREEN |   
FOREGROUND_BLUE);  
printf("**********************文件目录**********************\n");
char dirs [30];
while(true){
ZeroMemory(dirs,30);
iResult = recv(ConnectSocket,dirs,30,0);
//数据发送完成就跳出循环,结束时,服务器发过来quit
if(strcmp(dirs,quit)==0){
break;}
else
printf("%s\n",dirs);
if(SOCKET_ERROR == iResult)
{
printf("recvieve failed with error : %d\n",WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return -1;
}//if
//接收完再次返回
// continue;
}//while
continue;
}//if
if(strcmp(cmd,exit)==0){
break;}
if((strcmp(cmd,dir)!=0)&&(strcmp(cmd,exit)!=0)&&(strcmp(cmd,help)!=0)&&(strcmp(cmd,get)!=0)){
printf("命令参数:\n help----------获取命令帮助\n dir----------获取文件目录\n get----------下载文件\n exit----------退出\n");
continue;
} 
if(strcmp(cmd,get)==0){
SetConsoleTextAttribute(hout, FOREGROUND_INTENSITY | FOREGROUND_RED); 
printf("您输入的命令是get,下载文件,请依次输入要下载的文件名、保存本地文件名\n");
//文件下载 参数get后使用
char  str[20];
//文件名
scanf("%s",&str);
ZeroMemory(sendbuf,DEFAULT_BUFLEN);
strcpy(sendbuf,str);
if(strcmp(str,quit)==0){
printf("您输入了exit,退出get\n");
continue;
}
SetConsoleTextAttribute(hout,  
FOREGROUND_RED |   
FOREGROUND_GREEN |   
FOREGROUND_BLUE);  
iResult = send(ConnectSocket,sendbuf,strlen(sendbuf),0);
if(SOCKET_ERROR == iResult)
{
printf("send failed with error : %d\n",WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return -1;
}
//接收文件总大小
int size;
char sizestr [30];
recv(ConnectSocket,sizestr,30,0);
size = strtol (sizestr,NULL,10);
SetConsoleTextAttribute(hout,  
FOREGROUND_BLUE |   
FOREGROUND_RED);
printf("总的数据大小:%ld\n",size);
//cout<<"输入存放文件(路径+文件名):\n";
char    CFileName[DEFAULT_BUFLEN] = "";
scanf("%s",&CFileName);
SetConsoleTextAttribute(hout, FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN );
printf("保存文件:%s\n",CFileName);
outfile.open(CFileName,ios::out|ios::binary);
if(!outfile)   //打开文件准备写入
{    
printf("Error of opening file !");
iResult = shutdown(ConnectSocket, SD_SEND);
iResult = closesocket(ConnectSocket);
WSACleanup();
return -1;
}
COORD   coord;
CONSOLE_SCREEN_BUFFER_INFO csbi;
hout=GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hout,&csbi);
coord.X =csbi.dwCursorPosition.X;
coord.Y =csbi.dwCursorPosition.Y;
float cnt = 0;
while(issend)
{
//读取流 
rec = recv(ConnectSocket,szBuffer,BUFFER_SIZE,0);
cnt+=rec;
if(rec == 0)
{
SetConsoleTextAttribute(hout, FOREGROUND_INTENSITY | FOREGROUND_RED);
printf("Download completed ! \n");
break;
}
else if(rec == SOCKET_ERROR)
{
printf("Receive function failed with error : %d\n ",WSAGetLastError());
break;
}
SetConsoleCursorPosition(hout,coord);   
SetConsoleTextAttribute(hout, FOREGROUND_INTENSITY | FOREGROUND_GREEN);
printf("Received %f%% bytes \n",cnt/size*100);
outfile.write(szBuffer,rec);            
}
SetConsoleTextAttribute(hout, FOREGROUND_INTENSITY | FOREGROUND_BLUE);
printf("Transfer is completed!\n");
SetConsoleTextAttribute(hout, FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN );
outfile.close();    
}
// 若没有数据要发送,单向关闭连接
iResult = shutdown(ConnectSocket, SD_SEND);
// Step 6: 关闭连接
iResult = closesocket(ConnectSocket);
WSACleanup();
return 0;
}
}

效果:

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

计算传输的时间:

只要在传输文件的代码写上:

    time_t start ,end ;  
double cost;  
time(&start);  
printf("开始计算传输时间\n");

传输完成写上:

    //传输完成。输出时间
time(&end); 
cost=difftime(end,start); 
printf("传输时间:%f\n",cost);  

要加上windows.h和time.h

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/159257.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • Nginx出现403 forbidden

    Nginx出现403 forbiddennginx访问时报403,于是查看nginx日志,路径为/var/log/nginx/error.log。打开日志发现报错Permissiondenied,详细报错如下:1.open()"/data/www/1.txt"failed(13:Permissiondenied),client:192.168.1.194,server:www.web1.com,re…

  • c++面试选择题_C语言经典笔试题

    c++面试选择题_C语言经典笔试题1.new、delete、malloc、free关系delete会调用对象的析构函数,和new对应free只会释放内存,new调用构造函数。malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要…

  • apimodelproperty注解不生效(注解是什么)

    https://blog.csdn.net/weixin_44356055/article/details/109451892

  • 菜鸟的数学建模之路(一):最短路径算法「建议收藏」

    菜鸟的数学建模之路(一):最短路径算法「建议收藏」最短路径算法主要有两种,Dijkstra算法和floyd算法,当时在学习这两种算法时经常弄混了,关于这两种算法,记得当时是在交警平台设置的那一道题目上了解到的,就去查很多资料,花了不少时间才基本了解了这两种算法的基本用法,在总结的时候,我更多的是用代码的方式去做的总结,当时想的是等到要用的时候,直接改一下数据,运行代码,得到想要的最短路径就可以了。记得我们老师说过数学建模的知识没必要过于深入的去学…

  • 字符串转换系列三:VARIANT、COleVariant 和_variant_t

    字符串转换系列三:VARIANT、COleVariant 和_variant_tVARIANT、COleVariant和_variant_t  在OLE、ActiveX和COM中,VARIANT数据类型提供了一种非常有效的机制,由于它既包含了数据本身,也包含了数据的类型,因而它可以实现各种不同的自动化数据的传输。下面让我们来看看OAIDL.H文件中VARIANT定义的一个简化版:structtagVARIANT{ VARTYPEvt; 

  • 通俗的解释什么是Promise

    通俗的解释什么是Promise**说了这么多其实翻译成大白话就是:**1、媳妇儿饿了需要吃饭,所以我要上街买菜(**异步方法**)2、我什么时候买完菜回来她不知道(**异步方法执行几秒未知**),3、但是买完菜回到家之后我会马上做个红烧排骨给媳妇吃(**异步方法执行结束之后需要对返回值做处理**)这时候怎么办呢,就用promise(承诺):就说这个事情交给我吧,我承诺我去买菜,买完回来马上给你做红烧排骨,做完马上就叫你吃(这个地方相当于**promise链式调用**),你现在该干嘛干嘛去,去刷抖音,打游戏都可以(**不影响其他

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号