socket传输疑问。

客户端:
第一次:send(fd, buf, 30, 0);假设你的文件名和文件长度组成的buf一共30
第二次:send(fd,buf,filelength,0);将长度为filelength的内容发出去 (其实这里2次发送都要对发送长度做判断的,需要判断发送的长度是否是30或者filelength)

服务端:
第一次:recv(fd,buf,30,0);
解析长度为30的buf,得到filename和filelength
第二次:recv(fd,buf,filelength,0) (同样的这2次recv都要对recv的返回值做判断,收到的长度是否是30或者filelength)

当网络断开的时候是不是也是客户端断开呢,这个时候客户端只发了一半呢,怎么办

第二种情况,客户端发了200,你却只收了100,请问这是一个完整的文件吗

如果使用recv(fd,buf,filelength,0)来接收,而不是像我那样分批接收。假如发送的文件是1G大小,那您岂不是要消耗1G内存来分配给buf?如果发送的文件十几G,那一般人的计算机都会死机了吧。

给你发一段收发数据的代码,下面的代码中调用Socket::write或这Socket::read后都要对返回值做判断,即与他们的参数len做判断,凡是不等于len的返回值都是有问题的

//写数据
int Socket::write(const char *data, int len)
{
   if (_sockfd == -1)
   {
   return -1;
   }

   int lenToWritten = len;
   int totalLenWritten = 0;
   while(lenToWritten > 0)
   {
   int tmpLen;
   do {
   tmpLen = ::write(_sockfd, data+totalLenWritten, lenToWritten);
   if(errno == EPIPE)         //broken pipe  如果客户端或服务器断开连接,此时为断开的管道,无法写入,直接return
   {
   perror("error ");
   return -1;
   }
   if(tmpLen == 0)
   {
   perror("error");
   return -1;
   }
   } while (tmpLen < 0 /*&& errno == EINTR*/);
   lenToWritten -= tmpLen;
   totalLenWritten += tmpLen;
   }
   qDebug() << "totalLenWritten = " << totalLenWritten;
   return totalLenWritten;
}

//读数据
int Socket::read(char *data, int len)
{
   if (_sockfd == -1)
   {
   return -1;
   }

   int lenToRead = len;
   int totalLenRead = 0;
   while(lenToRead > 0)
   {
   int tmpLen;
   do {
   tmpLen = ::read(_sockfd, data+totalLenRead, lenToRead);
   if(tmpLen == 0)
   {
   qDebug() << "连接断开";
   return -1;
   }
   if(errno == EPIPE)
   {
   perror("error");
   return -1;
   }
   } while (tmpLen < 0 /*&& errno == EINTR*/);
   lenToRead -= tmpLen;
   totalLenRead += tmpLen;
   }
   qDebug() << "totalLenRead = " << totalLenRead;
   return totalLenRead;
}

缓冲区没那么大,当进行写的时候,写缓冲区已满,你是写不进去的,所以一般读和写都是循环

Socket::read(char data,int len)函数就是将len长度的数据可靠地保存到data指向的内存区域吧。函数内没发现将data写到文件的操作,只是不断移动data指针。所以data指向的内存区域的大小就是文件大小吧。所以我认为这段代码没有解决大文件传输问题。

我这段代码只是针对网络传输,你要写文件只需将收到的内容write到文件中即可

大文件,你可以考虑一次发多少,如1M,分多少次发送,每次发送调用该函数就行了,并不是一次发送完

以前用Qt写过一次C/S的程序。
TCP协议好像有个封包大小,就像adsl上网的tcp包默认大小一般是1492字节。一般来说,包越大传输越快,但这个默认包大小并不是固定值,网络质量不好,包小一点更好,可以避免发包经常出错(出错系统会自动重发,经常错就会经常重发)。

所以作为我们写程序,无法判断这个包到底是多大,也就不可能做到发送和接收动作是一一对应的。
发送的时候,可以简单地放入缓存,让协议自动发送,但接收的时候就必须做判断是否接收了一个完整的包。

一般解决这个方法,是发送一个大包时,在包头注明这个包的字节长度。
接收方首先接收并读取这个长度信息,然后循环接收,当接收的字节数达到长度时,停止接收进行处理。
然后再接收下一条内容。

:lol还是Qt简单,直接把一个类序列化成字节流,接收时把字节流再还源成一个类。。。
也不用操心字节序的问题。