C语言socket实现文件下载

C 专栏收录该内容
1 篇文章 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

  • 3
    点赞
  • 2
    评论
  • 11
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值