在windows 與Linux間實現文件傳輸(C++&C實現)


  要實現windows與linux間的文件傳輸,可以通過socket網絡編程來實現。

  這次要實現的功能與《Windows下通過socket進行字符串和文件傳輸》中實現的功能相同,即客戶端首先向服務器發送一個字符串,接着發送一個文件;服務器首先接收客戶端發送的字符串,作為文件名,接着接收客戶端發送的文件並保存到本地。

  以window平台程序作為客戶端,linux平台的程序作為服務器,並且是在局域網范圍內進行文件傳輸。

  windows客戶端的實現:

  客戶端程序在VS2012 IDE下編譯運行,依舊使用在《Windows下通過socket進行字符串和文件傳輸》中簡單封裝實現的FileTransfer類,通過聲明一個FileTransfer對象並調用相應的函數來發送數據和文件。其main函數如下:

/************************************************************************* 
  > File Name: 客戶端主函數
  >Author: xiongmao
  >Purpose:在主函數中聲明文件傳輸類的一個具體對象,向linux服務器發送文件
 ************************************************************************/ 

#include <iostream>
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include "file_transfer.h"
using namespace std;

int PORT;
string SERVER_IP ="127.0.0.1" ;
#define BUFFER_SIZE 1024 
#define FILE_NAME_MAX_SIZE 512 
#pragma comment(lib, "WS2_32") 
 
int main() 
{ 
    cout<<"input ip and port"<<endl;
    cin>>SERVER_IP>>PORT;
    while(1)
    {
        bool flag;
        string filename;
        printf("input file name:");
        cin>>filename;
        FileTransfer ft;
        ft.setIpAndPort(SERVER_IP,PORT);
        ft.setFilePath(filename);
        flag=ft.sendFile(filename,filename);
        if (flag)
        { 
            printf("send file %s success \n",filename.c_str());
        } 
        else
        {
            printf("send file %d fail.The error code is : %d \n",GetLastError());
        }
    }
    system("pause");
    return 0; 
} 

  在主函數開始時,首先輸入服務器的ip地址和端口,接着輸入想要發送的文件名(文件應在源碼目錄下存在),客戶端就可完成文件袋額發送。

 

  linux服務器的代碼:

  linux下僅使有一個main.cpp文件,實現簡單的服務器功能,其代碼如下:

//main.cpp

#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h> 

#include <stdio.h>          
#include <stdlib.h>         
#include <string.h>         

#define HELLO_WORLD_SERVER_PORT 8989  
#define LENGTH_OF_LISTEN_QUEUE 20  
#define BUFFER_SIZE 1024  
  
int main(int argc, char **argv)  
{  
    struct sockaddr_in server_addr;  
    int server_socket;  
    int opt = 1;  
     
    bzero(&server_addr,sizeof(server_addr));   
      
    server_addr.sin_family = AF_INET;  
    server_addr.sin_addr.s_addr = htons(INADDR_ANY);  
    server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT); 
  
    /* create a socket */  
    server_socket = socket(PF_INET,SOCK_STREAM,0);  
    if( server_socket < 0)  
    {  
        printf("Create Socket Failed!");  
        exit(1);  
    }  
   
    setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); 
    if( bind(server_socket,(struct sockaddr*)&server_addr,sizeof(server_addr)))  
    {  
        printf("Server Bind Port : %d Failed!", HELLO_WORLD_SERVER_PORT);   
        exit(1);  
    }  

    if(listen(server_socket, LENGTH_OF_LISTEN_QUEUE))  
    {  
        printf("Server Listen Failed!");   
        exit(1);  
    }  
       
    while (true)
    {
        printf("wait for file transfer...\n");
        char file_name[BUFFER_SIZE];
        char buffer[BUFFER_SIZE];

        struct sockaddr_in client_addr; 
        socklen_t client_addr_len = sizeof(client_addr); 
        //首先接收發送過來的字符串
        int newSocket = accept( m_Socket, (sockaddr *)&client_addr, &client_addr_len);
        if (newSocket < 0) 
        { 
            printf("Server Accept Failed: %d", WSAGetLastError()); 
            continue; 
        } 
        memset(buffer,0,sizeof(buffer));
        memset(file_name,0,sizeof(file_name));
        if (recv(newSocket,buffer,sizeof(buffer),0)<0)
        {
            printf("recv file name fail!\n");
            close(newSocket);
            continue;
        }
        strncpy(file_name,buffer,strlen(buffer));
        printf("recv file name : %s \n",file_name);
        FILE * fp = fopen(file_name,"wb");
        if (fp==NULL)
        {
            printf("open file error\n");
            continue;
        }
        //獲取字符串后繼續獲取文件數據
        memset(buffer, 0, BUFFER_SIZE); 
        int length = 0; 
        while ((length = recv(newSocket, buffer, BUFFER_SIZE, 0)) > 0) 
        { 
            if (fwrite(buffer, sizeof(char), length, fp) < length) 
            { 
                printf("File: %s Write Failed\n", file_name); 
                break; 
            } 
            memset(buffer, 0, BUFFER_SIZE); 
        }
        fclose(fp);
        close(newSocket);
        printf("file transfer success!\n"); 
    }
      
    close(server_socket);  
    return 0;  
}  

   在linux下,進入main.cpp所在的目錄,使用命令

gcc main.cpp -o main.out

來編譯服務器端程序,再使用命令

./main.out

 來執行編譯的程序,即可啟動服務器。

 

  通過比較《Windows下通過socket進行字符串和文件傳輸》中服務器程序的實現,觀察到代碼實現基本上一致,linux下的實現存在以下幾點不同:

  1、linux下用來綁定端口,實現監聽的socket server_socket的聲明為int類型,而在window下則為SOCKET類型。

  2、linux下,關閉socket的函數為close,使用該函數需要包含unistd.h頭文件,windows下則是用closesocket來關閉socket。

  3、使用bzero函數來進行置零操作。bzero函數不是標准函數,不推薦使用。非標准函數的使用會對程序的移植造成不便。bzero函數的功能可以用memset函數來實現。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM