程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> C語言入門知識 >> C語言socket實現文件下載

C語言socket實現文件下載

編輯:C語言入門知識

是網絡編程的作業,我比較菜。寫到定位輸出,做百分比出現了問題,不顯示0到100的,直接從0跳到了100。請教了下大佬。改了過來。原來是類型的問題,做出來的運算應該是float,但是我都定義的int,輸出也是,大佬指出後,我好尴尬。犯了小錯誤。但是在這次過程也學習了一波。要加油了!代碼寫的這麼亂!
寫的是帶顏色的版本,顏色有可能會覺得妖艷,好吧。
編譯平台是vc++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;

}
}

效果:

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved