Я настроил простую передачу файлов по протоколу 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 заключается в том, чтобы избежать подобных проблем.
(чтобы отдать должное, для моего сервера и клиентского кода я много позаимствовал из книги «Полное руководство по сетевому программированию в Linux» Дэвиса, Тернера и Yocom от Apress)