要實現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函數來實現。