我已经设置了一个简单的 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的全部目的就是为了避免这种问题。
(为了给予应有的认可,我的服务器和客户端代码大量借鉴了 Apress 的 Davis、Turner 和 Yocom 所著的《Linux 网络编程权威指南》一书)