gpt4 book ai didi

unix - TCP 连接似乎接收到不完整的数据

转载 作者:可可西里 更新时间:2023-11-01 02:33:15 24 4
gpt4 key购买 nike

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

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

#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);

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

对于服务器:

#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 变量偶尔不会包含与发送的文件相同的大小,但有时会。

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

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

(为了获得应有的荣誉,我的服务器和客户端代码大量借鉴了这本书:The Definitive Guide to Linux Network Programming,作者是 Apress 的 Davis、Turner 和 Yocom)

最佳答案

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

更新:

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

关于unix - TCP 连接似乎接收到不完整的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1837444/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com