上位机和下位机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. }

 

posted @ 2021-04-05 18:51  秦汉思源  阅读(4256)  评论(0编辑  收藏  举报