欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C语言socket实现文件下载

程序员文章站 2023-02-02 09:12:55
是网络的作业,我比较菜。写到定位输出,做百分比出现了问题,不显示0到100的,直接从0跳到了100。请教了下大佬。改了过来。原来是类型的问题,做出来的运算应该是float,但是我都定义的int,输出...

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

还是有点bug,有时,客户端发dir命令时会退出。有空再看看。这几天太忙。萌新的我只会点c,不会c++。如有错误,望大佬指出。谢谢。

sever:

#include
#include
#include
#include
#include
#include
#include  
#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
#include
#include
#include
#include
#include
#include

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,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;

}
}

效果:

C语言socket实现文件下载

C语言socket实现文件下载

C语言socket实现文件下载

C语言socket实现文件下载