要实现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 ",filename.c_str()); } else { printf("send file %d fail.The error code is : %d ",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... "); 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! "); close(newSocket); continue; } strncpy(file_name,buffer,strlen(buffer)); printf("recv file name : %s ",file_name); FILE * fp = fopen(file_name,"wb"); if (fp==NULL) { printf("open file error "); 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 ", file_name); break; } memset(buffer, 0, BUFFER_SIZE); } fclose(fp); close(newSocket); printf("file transfer success! "); } 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函数来实现。