TCP 连接似乎接收到不完整的数据 [英] TCP Connection Seems to Receive Incomplete Data

查看:77
本文介绍了TCP 连接似乎接收到不完整的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经设置了一个简单的 TCP 文件传输.一切似乎都正常,除了接收到的文件大小偶尔小于发送的文件大小.接收文件的大小似乎没有任何规律.

I've setup a simple TCP file transfer. Everything appears to work OK, except for the received file size is sporadically a smaller size than the file that was sent. There doesn't appear to be any pattern to the size of the received file.

(在下面的代码中,注意典型的客户端/服务器滚动是颠倒的)我的客户端代码是这样的:

(in the code below, note that the typical client/server rolls are reversed) My client code is like:

#define kMaxBacklog (5)
// fill out the sockadd_in for the server
struct sockaddr_in servAdddress;
//memcpy() to fill in the sockaddr

//setup the socket
int sockd, returnStatus;    
sockd = socket(AF_INET, SOCK_STREAM, 0);
if (sockd == -1)
    NSLog(@"could not create client socket");
else
    NSLog(@"created client socket");

returnStatus = connect(sockd, (struct sockaddr*)&servAdddress, sizeof(servAdddress));
if (returnStatus == -1)
    NSLog(@"could not connect to server - errno:%i", errno);
else
    NSLog(@"connected to server"); 

NSData *dataWithHeader = [self getDataToSend];
returnStatus = send(sockd, [dataWithHeader bytes], [dataWithHeader length], 0);
if (returnStatus == -1)
    NSLog(@"could not send file to server");
else if( returnStatus < [dataWithHeader length])
    NSLog(@"ONLY PARTIAL FILE SENT");
else
    NSLog(@"file sent of size: %i", returnStatus);

shutdown(sockd, SHUT_WR);
close(sockd);

客户端方法总是报告它发送了整个文件.

The client method ALWAYS reports that it sent the entire file.

对于服务器:

#define MAXBUF (10000)
int _socket;
_socket = socket(AF_INET, SOCK_STREAM, 0); // set up the socket 

struct sockaddr_in addr; 
bzero(&addr, sizeof(addr)); 
addr.sin_len = sizeof(addr); 
addr.sin_family = AF_INET; 
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(0); 

int retval = bind(_socket, (struct sockaddr *)&addr, sizeof(addr)); 
    if (retval == -1)
        NSLog(@"server could not bind to socket");
    else 
        NSLog(@"server socket bound");

socklen_t len = sizeof(addr); 
retval = getsockname(_socket, (struct sockaddr *)&addr, &len);
    if (retval == -1)
        NSLog(@"server could not get sock name");
    else 
        NSLog(@"server socket name got");

    int socket1, socket2, clientAddrLen, returnStatus;
    struct sockaddr_in servAdddress, clientAddress;
    clientAddrLen = sizeof(servAdddress);

    socket1 = _socket;

    returnStatus = listen(socket1, kMaxBacklog);
    if (returnStatus == -1)
        NSLog(@"server could not listen on socket");
    else
        NSLog(@"server socket listening");

while(1){
    FILE *fd;
    int i, readCounter;
    char file[MAXBUF];

    NSLog(@"server blocking on accept()");
    socket2 = accept(socket1, (struct sockaddr*)&clientAddress, (socklen_t*)&clientAddrLen);
    if (socket2 == -1)
        NSLog(@"server could not accpet the connection");
    else
        NSLog(@"server connection accepted");

    i = 0;
    readCounter = recv(socket2, file, MAXBUF, 0);
    if(!readCounter)
        NSLog(@"server connection cancelled, readCount = 0");

        else if (readCounter == -1){
        NSLog(@"server could not read filename from socket");
        close(socket2);
        continue;
    }
    else
        NSLog(@"server reading file of size: %i", readCounter);


    fd = fopen([myfilePathObject cStringUsingEncoding:NSASCIIStringEncoding], "wb");

    if(!fd){
        NSLog(@"server could not open the file for creating");
        close(socket2);
        continue;
    }
    else
        NSLog(@"server file open for creating");

    returnStatus = fwrite([myData bytes], 1, [myData length], fd);
    if (returnStatus == -1)
        NSLog(@"Error writing data to server side file: %i", errno);
    else
        NSLog(@"file written to disk);

    readCounter = 0;
    //close (fd);
    returnStatus = fclose(fd);
    if(returnStatus)
        NSLog(@"server error closing file");

偶尔,readCounter 变量包含的大小与发送的文件的大小不同,但有时确实如此.

So sporadically, the readCounter variable will not contain the same size as the file that was sent, but some times it does.

如果文件传输发生在 iPhone 和 iPhone 模拟器之间,两者都通过 WIFI 传输.无论手机是服务器还是模拟器是服务器,都会发生这种情况.

If it matters the file transfer is occurring between an iPhone and an iPhone simulator, both over WIFI. This happens regardless of if the phone is the server or if the simulator is the server.

如果有人能帮助我理解为什么会发生这种情况,我将不胜感激.我以为TCP的全部目的就是为了避免这种问题.

If anyone can help me understand why this is occurring I'd appreciate it. I thought the whole purpose of TCP was to avoid this kind of problem.

(为了感谢我的服务器和客户端代码,我大量借用了这本书:Linux 网络编程权威指南,作者是 Apress 的 Davis、Turner 和 Yocom)>

推荐答案

recv 函数只能接收 1 个字节,您可能需要多次调用它才能获得整个有效负载.因此,您需要知道期望的数据量.尽管您可以通过关闭连接来表示完成,但这并不是一个好主意.

The recv function can receive as little as 1 byte, you may have to call it multiple times to get your entire payload. Because of this, you need to know how much data you're expecting. Although you can signal completion by closing the connection, that's not really a good idea.

更新:

我还应该提到 send 函数与 recv 具有相同的约定:你必须在循环中调用它,因为你不能假设它会发送你所有的数据.虽然它可能始终适用于您的开发环境,但这种假设会在以后让您感到厌烦.

I should also mention that the send function has the same conventions as recv: you have to call it in a loop because you cannot assume that it will send all your data. While it might always work in your development environment, that's the kind of assumption that will bite you later.

这篇关于TCP 连接似乎接收到不完整的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆