在Ubuntu局域网搭建以后,我们的目的是实现通讯,传输文件,目前主流的方式是TCP(传输控制协议) 和UDP (数据报)的方式来实现。考虑到TCP传输不会丢数据,因此在这里对于文件传输是通过TCP(传输控制协议)Socket套接字来实现的。关于上位机和下位机TCP/IP通讯的实现的代码如下,目前已经实现了可以传输任何类型的文件。(Ubuntu下Socket和Windows下略有不同,因为项目需要,做了一个Ubuntu下的小demo,有需要参考的同学可以参考,注意在输入文件的名字中不要有类似于“/”,"_"这样的符号出现)。下图是TCP/IP 通讯的实现流程。本文demo 使用方法,首先将服务端和客户端源码编译得到可执行文件,然后在服务端运行可执行文件,最后客户端可执行文件,比如服务端可执行文件的名字为 Client,则在相应终端输入 ./Client 192.168.1.1, 然后回车(这里192.168.1.1为客户端的IP地址,根据自己实际情况设置)。
C++代码实现如下:
Client.cpp
- #include <stdio.h>
- #include <errno.h>
- #include <string.h>
- #include <netdb.h>
- #include <sys/types.h>
- #include <netinet/in.h>
- #include <sys/socket.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <arpa/inet.h>
- #include <netdb.h>
- #define MAXLINE 1024*1024
- #define FILE_NAME_MAX_SIZE 1024
- int main(int argc, char** argv){
- int sockfd, len;
- char buffer[MAXLINE];
- struct sockaddr_in servaddr;
- FILE *fq;
- if( argc != 2)
- {
- printf("usage: ./client <ipaddress>\n");
- return 0;
- }
- // 创建socket
- if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
- {
- printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);
- return 0;
- }
- memset(&servaddr, 0, sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- servaddr.sin_port = htons(6666);
- if( inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
- {
- printf("inet_pton error for %s\n",argv[1]);
- return 0;
- }
- // 连接远程服务器
- if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
- {
- printf("connect error: %s(errno: %d)\n",strerror(errno),errno);
- return 0;
- }
- //输入要发送的文件
- char filename[FILE_NAME_MAX_SIZE];
- bzero(filename,FILE_NAME_MAX_SIZE);
- printf("Please input the file name you want to send:");
- scanf("%s",&filename);
- getchar();
- if(( fq = fopen(filename,"rb")) == NULL )
- {
- printf("File open.\n");
- close(sockfd);
- exit(1);
- }else
- {
- bzero(buffer,sizeof(buffer));
- while(!feof(fq))
- {
- len = fread(buffer, sizeof(char), sizeof(buffer), fq);
- if(len != write(sockfd, buffer, len))
- {
- printf("write.\n");
- break;
- }
- }
- }
- fclose(fq);
- close(sockfd);
- return 0;
- }
服务端代码:
Server.cpp
- #include<stdio.h>
- #include<stdlib.h>
- #include<string.h>
- #include<errno.h>
- #include<sys/types.h>
- #include<sys/socket.h>
- #include<netinet/in.h>
- #include<unistd.h>
- #include<time.h>
- #define MAXLINE 1024*1024
- #define FILE_NAME_MAX_SIZE 512
- int main(int argc, char** argv){
- int listenfd, connfd1;
- clock_t start,end;
- double duration;
- struct sockaddr_in servaddr;
- char buff[MAXLINE];
- char filename[FILE_NAME_MAX_SIZE];
- int count;
- bzero(buff,MAXLINE);
- int m,n;
- FILE *fp = NULL;
- system("clear");
- if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
- {
- printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
- return 0;
- }
- printf("----init socket----\n");
- memset(&servaddr, 0, sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
- servaddr.sin_port = htons(6666);
- //设置端口可重用
- int contain;
- setsockopt(listenfd,SOL_SOCKET, SO_REUSEADDR, &contain, sizeof(int));
- //绑定
- if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1)
- {
- printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
- return 0;
- }
- printf("----bind sucess----\n");
- //监听
- if( listen(listenfd, 10) == -1)
- {
- printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
- return 0;
- }
- printf("======waiting for client's request======\n");
- struct sockaddr_in client_addr;
- socklen_t size=sizeof(client_addr);
- if( (connfd1 = accept(listenfd, (struct sockaddr*)&client_addr, &size)) == -1)
- {
- printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
- //continue;
- }
- //recv file imformation
- start = clock();
- count=recv(connfd1,buff,sizeof(buff),0);
- //count=read(connfd1,filename,sizeof(filename));
- if(count<0)
- {
- perror("recv");
- exit(1);
- }
- memset(filename,'\0',sizeof(filename));
- strncpy(filename,buff,strlen(buff)>FILE_NAME_MAX_SIZE?FILE_NAME_MAX_SIZE:strlen(buff));
- printf("Preparing recv file : %s\n",filename);
- if((fp = fopen(filename,"wb+")) == NULL)
- {
- printf("File build failed!.\n");
- close(listenfd);
- exit(1);
- }
- bzero(buff,MAXLINE);
- while(n=recv(connfd1,buff,MAXLINE,0))
- {
- if(n<0)
- {
- perror("recv");
- exit(1);
- }
- int writelen=fwrite(buff,1,n,fp);
- if(writelen<n)
- {
- perror("write error!");
- exit(1);
- }
- bzero(buff,MAXLINE);
- }
- end = clock();
- duration = (double)(end-start)/double(CLOCKS_PER_SEC);
- printf("本次传输总共耗时:%f 秒\n",duration);
- printf("Receieved file:%s finished!\n",filename);
- fclose(fp);
- fp = NULL;
- close(connfd1);
- close(listenfd);
- return 0;
- }