QT编写多线程TCP文件接收服务器


本文介绍的是QT 多线程 TCP 文件接收服务器实例,如果你想深入了解这方面的资料的话,请关注本文末尾,不多说,我们先来看内容。

因为项目需要,需要跨平台编写网络传输程序。

目标:

用户端:Linux(arm平台),完成文件的传输

服务器:Windows ,使用多线程的文件的接收

实现无线的文件传输功能

用户端程序,用标准的socket完成文件传输的功能,代码如下:

  1.  // Linux下网络编程,客户端程序代码    
  2.  
  3.  //程序运行参数:    
  4.  // ./client IPADDRESS PORTNUMBER    
  5.  // (其中IPADDRESS是服务端IP地址,PORTNUMBER是服务端用于监听的端口)    
  6.  //    
  7.    
  8.  #include <stdio.h> 
  9.  #include <stdlib.h> 
  10.  #include <errno.h> 
  11.  #include <string.h> 
  12.  #include <netdb.h> 
  13.  #include <ctype.h> 
  14.  #include <unistd.h> 
  15. #include <sys/types.h> 
  16.  #include <sys/socket.h> 
  17.   #include <netinet/in.h> 
  18. #include <sys/time.h> 
  19.  
  20.  //用这个my_read()函数代替本来的read()函数原因有以下几点:   
  21. //   
  22.  //ssize_t read(int fd,void *buf,size_t nbyte)   
  23. //read函数是负责从fd中读取内容。当读成功时,read返回实际所读的字节数;如果   
  24.  //返回的值是0,表示已经读到文件的结束了;小于0表示出现了错误。   
  25.  //   
  26.  // 1)如果错误为EINTR说明read出错是由中断引起的,继续读。   
  27.  // 2)如果是ECONNREST表示网络连接出了问题,www.bkjia.com停止读取。   
  28.  
  29.  size_t min(size_t a,size_t b)  
  30. {  
  31.  return( (a<b) ? a : b);  
  32.  }  
  33.    
  34.  ssize_t my_write(int fd,void *buffer,size_t length)  
  35. {  
  36.  size_t bytes_left; //尚未写的文件大小   
  37.  size_t writesize = 4* 1024;  
  38.  ssize_t written_bytes; //已经写的文件大小   
  39.  char *ptr;  
  40.  ptr=buffer;  
  41. bytes_left=length;  
  42.   while(bytes_left>0)  
  43.  {  
  44.  //开始写   
  45.  written_bytes=write(fd,ptr,min(bytes_left,writesize));  
  46.  //出现了写错误   
  47. if(written_bytes<=0)  
  48.  {  
  49.  //中断错误,置零重新写   
  50. if(errno==EINTR)  
  51. written_bytes=0;  
  52.  //其他错误,退出不写了   
  53.  else   
  54.  return(-1);  
  55. }  
  56.  //从剩下的地方继续写   
  57. bytes_left-=written_bytes;  
  58.  ptr+=written_bytes;  
  59.  }  
  60. return(0);  
  61. }  
  62.  
  63. : int main(int argc, char *argv[])  
  64. {  
  65.  int sockfd; //通信套接字描述符   
  66. char *buffer; //缓冲区   
  67. struct sockaddr_in server_addr; //服务器地址结构   
  68.  struct hostent *host; //主机地址与名称信息结构www.bkjia.com   
  69.  int nbytes; //端口号、字节数   
  70.  FILE *fp; //文件指针   
  71. int nfilesize; //文件大小   
  72.  char str[128]; //文件名   
  73.  char yes='Y'; //流程控制   
  74.  struct timeval tpstart,tpend; //用于记录文件传输时间   
  75.  float timeuse; //文件传输所用时间   
  76. char *hostname="127.0.0.1";//主机名/ip地址   
  77.  int portnumber=4321;//端口号   
  78.    
  79.  //提示用户输入完整的命令行参数   
  80.  if(argc!=3)  
  81.  {  
  82.  fprintf(stderr,"Usage:%s hostname portnumber\a\n",argv[0]);  
  83.  printf("using defaults:\nhostname: %s\nportnumber: %d\n",hostname,portnumber);  
  84.  }  
  85.  
  86.  //如果利用用户输入的域名无法获得正确的主机地址信息,则退出   
  87.  if (argc>1)  
  88.  {  
  89.  if((host=gethostbyname(argv[1]))==NULL)  
  90. {  
  91.  fprintf(stderr,"Gethostname error\n");  
  92. exit(1);  
  93.  }  
  94.  }  
  95.  
  96. else   
  97.  if((host=gethostbyname(hostname))==NULL)  
  98.  {  
  99. fprintf(stderr,"Gethostname error\n");  
  100.  exit(1);  
  101. }   
  102. if(argc>2)  
  103.  //如果用户输入的端口不正确,则提示并退出   
  104.  if((portnumber=atoi(argv[2]))<0)  
  105. {  
  106. fprintf(stderr,"Usage:%s hostname portnumber\a\n",argv[0]);  
  107.  exit(1);  
  108. }  
  109. //客户程序开始建立 sockfd描述符,创建通信套接字   
  110.  if((sockfd=socket(AF_INET,SOCK_STREAM,6))==-1)  
  111. {  
  112.  fprintf(stderr,"Socket Error:%s\a\n",strerror(errno));  
  113. exit(1);  
  114.  }  
  115. //客户程序填充服务端的地址信息   
  116.  bzero(&server_addr,sizeof(server_addr));  
  117.  server_addr.sin_family=AF_INET;  
  118.  server_addr.sin_port=htons(portnumber);  
  119.  server_addr.sin_addr=*((struct in_addr *)host->h_addr);   
  120. //客户程序发起连接请求    
  121. if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)  
  122.  {  
  123.  fprintf(stderr,"Connect Error:%s\a\n",strerror(errno));  
  124.  exit(1);  
  125. }  
  126.  printf("Connection Succeed!\n");  
  127.  while (toupper(yes)=='Y')  
  128.  {  
  129.  //提示用户输入文件路径   
  130.  printf("Please input the file location:");  
  131.  scanf("%s",str);  
  132.  while ((fp=fopen(str,"r"))==NULL)  
  133. {  
  134.  fprintf(stderr,"File open error,Retry!\n");  
  135.  printf("Please input the file location:");  
  136.  scanf("%s",str);  
  137.  //exit(1);   
  138.  }  
  139.   getchar();  
  140.    
  141.  //获取打开的文件的大小,www.bkjia.com并将文件整个读入内存中   
  142.  fseek(fp,0L,SEEK_END);  
  143.  nfilesize=ftell(fp);  
  144.  rewind(fp);//most important!!!!!   
  145.  char *p=(char *)malloc(nfilesize);  
  146. if (fread((void *)p,nfilesize,1,fp)<1) {  
  147. if (feof(fp))  
  148. printf("read end of file!\nquit!\n");  
  149. else   
  150.  printf("read file error!\n");  
  151.  }  
  152.  //将要传输的文件的大小信息发送给客户端   
  153.  if (my_write(sockfd,(void *)&nfilesize,4)==-1)  
  154. {  
  155.  fprintf(stderr,"Write Error:%s\n",strerror(errno));  
  156. exit(1);  
  157. }  
  158.  printf("Begin to transfer the file!\n");  
  159. getchar();  
  160.  
  161. //获取传输初始时间   
  162. gettimeofday(&tpstart,NULL);  
  163.  
  164.  //传输文件   
  165. if (my_write(sockfd,p,nfilesize)==-1)  
  166.   {  
  167. fprintf(stderr,"Transfer failed!");  
  168.  exit(1);  
  169.  }  
  170.  //获取传输结束时间   
  171.  gettimeofday(&tpend,NULL);  
  172. //计算整个传输用时   
  173. timeuse=1000000*(tpend.tv_sec-tpstart.tv_sec)+(tpend.tv_usec-tpstart.tv_usec);  
  174. timeuse/=1000000;   
  175.  printf("Transfer Succeed!\nFile Name: %s\nFile Size: %d bytes\nTotal Time: 
  176. %f seconds\nTransfer Speed: %f bytes/second",str,nfilesize,timeuse,((float)nfilesize)/timeuse);  
  177.  free(p); //释放文件内存   
  178.  fclose(fp); //关闭文件   
  179.  // printf("\nTransfer another file?(Y/N): ");   
  180.  //scanf("%c",&yes);   
  181. // getchar();   
  182.  yes='n';  
  183.  }  
  184.  //结束通讯,关闭套接字,www.bkjia.com关闭连接   
  185.  close(sockfd);  
  186.  printf("\nClient Exit!~~\n");  
  187.  exit(0);  
  188.  } 

服务器端代码列表:

具体代码如下:

  1. “tcpserver.h”  
  2. #ifndef TCPSERVER_H  
  3.  #define TCPSERVER_H   
  4.  #include <QTcpServer> 
  5.  //继承自QTcpServer,完成TCPSEVER的建立的类   
  6.  class TcpServer : public QTcpServer  
  7. {  
  8. Q_OBJECT  
  9.  public:  
  10.  explicit TcpServer(QObject *parent = 0);  
  11.   //此信号用来更新UI   
  12.  signals:  
  13. void bytesArrived(qint64,qint32,int);  
  14. //QTcpServer类自带的函数,详情参考Class Reference   
  15. protected:  
  16.  void incomingConnection(int socketDescriptor);  
  17. };  
  18.  #endif // TCPSERVER_H  

TCPSERVER继承QTcpServer,主要完成TCP服务器的建立,类中最主要的成员函数为虚函数incomingConnection(int socketDescriptor)的定义。

  • 1
  • 2
  • 下一页
【内容导航】
第1页:QT 多线程 TCP 文件接收服务器 第2页:tcpserver.cpp

相关内容