在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;
- }