上位機和下位機TCP/IP 通訊實現


在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

  1. #include <stdio.h>
  2. #include <errno.h>
  3. #include <string.h>
  4. #include <netdb.h>
  5. #include <sys/types.h>
  6. #include <netinet/in.h>
  7. #include <sys/socket.h>
  8. #include <stdlib.h>
  9. #include <unistd.h>
  10. #include <arpa/inet.h>
  11. #include <netdb.h>
  12. #define MAXLINE 1024*1024
  13. #define FILE_NAME_MAX_SIZE 1024
  14. int main(int argc, char** argv){
  15. int sockfd, len;
  16. char buffer[MAXLINE];
  17. struct sockaddr_in servaddr;
  18. FILE *fq;
  19. if( argc != 2)
  20. {
  21. printf("usage: ./client <ipaddress>\n");
  22. return 0;
  23. }
  24. // 創建socket
  25. if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  26. {
  27. printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);
  28. return 0;
  29. }
  30. memset(&servaddr, 0, sizeof(servaddr));
  31. servaddr.sin_family = AF_INET;
  32. servaddr.sin_port = htons(6666);
  33. if( inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
  34. {
  35. printf("inet_pton error for %s\n",argv[1]);
  36. return 0;
  37. }
  38. // 連接遠程服務器
  39. if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
  40. {
  41. printf("connect error: %s(errno: %d)\n",strerror(errno),errno);
  42. return 0;
  43. }
  44. //輸入要發送的文件
  45. char filename[FILE_NAME_MAX_SIZE];
  46. bzero(filename,FILE_NAME_MAX_SIZE);
  47. printf("Please input the file name you want to send:");
  48. scanf("%s",&filename);
  49. getchar();
  50. if(( fq = fopen(filename,"rb")) == NULL )
  51. {
  52. printf("File open.\n");
  53. close(sockfd);
  54. exit(1);
  55. }else
  56. {
  57. bzero(buffer,sizeof(buffer));
  58. while(!feof(fq))
  59. {
  60. len = fread(buffer, sizeof(char), sizeof(buffer), fq);
  61. if(len != write(sockfd, buffer, len))
  62. {
  63. printf("write.\n");
  64. break;
  65. }
  66. }
  67. }
  68. fclose(fq);
  69. close(sockfd);
  70. return 0;
  71. }

服務端代碼:

Server.cpp

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4. #include<errno.h>
  5. #include<sys/types.h>
  6. #include<sys/socket.h>
  7. #include<netinet/in.h>
  8. #include<unistd.h>
  9. #include<time.h>
  10. #define MAXLINE 1024*1024
  11. #define FILE_NAME_MAX_SIZE 512
  12. int main(int argc, char** argv){
  13. int listenfd, connfd1;
  14. clock_t start,end;
  15. double duration;
  16. struct sockaddr_in servaddr;
  17. char buff[MAXLINE];
  18. char filename[FILE_NAME_MAX_SIZE];
  19. int count;
  20. bzero(buff,MAXLINE);
  21. int m,n;
  22. FILE *fp = NULL;
  23. system("clear");
  24. if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
  25. {
  26. printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
  27. return 0;
  28. }
  29. printf("----init socket----\n");
  30. memset(&servaddr, 0, sizeof(servaddr));
  31. servaddr.sin_family = AF_INET;
  32. servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  33. servaddr.sin_port = htons(6666);
  34. //設置端口可重用
  35. int contain;
  36. setsockopt(listenfd,SOL_SOCKET, SO_REUSEADDR, &contain, sizeof(int));
  37. //綁定
  38. if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1)
  39. {
  40. printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
  41. return 0;
  42. }
  43. printf("----bind sucess----\n");
  44. //監聽
  45. if( listen(listenfd, 10) == -1)
  46. {
  47. printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
  48. return 0;
  49. }
  50. printf("======waiting for client's request======\n");
  51. struct sockaddr_in client_addr;
  52. socklen_t size=sizeof(client_addr);
  53. if( (connfd1 = accept(listenfd, (struct sockaddr*)&client_addr, &size)) == -1)
  54. {
  55. printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
  56. //continue;
  57. }
  58. //recv file imformation
  59. start = clock();
  60. count=recv(connfd1,buff,sizeof(buff),0);
  61. //count=read(connfd1,filename,sizeof(filename));
  62. if(count<0)
  63. {
  64. perror("recv");
  65. exit(1);
  66. }
  67. memset(filename,'\0',sizeof(filename));
  68. strncpy(filename,buff,strlen(buff)>FILE_NAME_MAX_SIZE?FILE_NAME_MAX_SIZE:strlen(buff));
  69. printf("Preparing recv file : %s\n",filename);
  70. if((fp = fopen(filename,"wb+")) == NULL)
  71. {
  72. printf("File build failed!.\n");
  73. close(listenfd);
  74. exit(1);
  75. }
  76. bzero(buff,MAXLINE);
  77. while(n=recv(connfd1,buff,MAXLINE,0))
  78. {
  79. if(n<0)
  80. {
  81. perror("recv");
  82. exit(1);
  83. }
  84. int writelen=fwrite(buff,1,n,fp);
  85. if(writelen<n)
  86. {
  87. perror("write error!");
  88. exit(1);
  89. }
  90. bzero(buff,MAXLINE);
  91. }
  92. end = clock();
  93. duration = (double)(end-start)/double(CLOCKS_PER_SEC);
  94. printf("本次傳輸總共耗時:%f 秒\n",duration);
  95. printf("Receieved file:%s finished!\n",filename);
  96. fclose(fp);
  97. fp = NULL;
  98. close(connfd1);
  99. close(listenfd);
  100. return 0;
  101. }

 


免責聲明!

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



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