我遇到了写功能无法正常工作的问题,如果它放在一个没有睡眠的循环中。我想要实现的是将文件从本地机器传输到远程FTP服务器以下代码工作正常但是写入函数没有正确传输字节,它只传输半个字节,它可以正常工作,睡眠阻塞循环。
struct sockaddr_in
{
int16_t sin_family;
uint16_t sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
struct in_addr
{
uint32_t s_addr;
};
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
int isocket = socket(AF_INET,SOCK_STREAM,0);
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("some ip goes here");
servaddr.sin_port = htons(21);
char buf[1024];
int MAX_LENGTH = 1024;
char readBuf[MAX_LENGTH];
long cmd;
int res = connect(isocket, (struct sockaddr_in *)&servaddr, sizeof(servaddr));
if(res < 0) {
NSLog(@"problem connecting to server");
}
recv(isocket, (void *)readBuf,MAX_LENGTH, 0);
NSLog(@"response: %s",readBuf);
NSLog(@"Issuing command");
strcpy(buf, "USER foo\r\n");
cmd = send(isocket, (void *)buf, strlen(buf), 0); //send username
recv(isocket, (void *)readBuf,MAX_LENGTH, 0);
NSLog(@"response: %s",readBuf); //read response
strcpy(buf, "PASS *******\r\n");
cmd = send(isocket, (void *)buf, strlen(buf), 0);//send password
recv(isocket, (void *)readBuf, MAX_LENGTH, 0);
NSLog(@"response: %s",readBuf); //read response
strcpy(buf, "CWD /httpdocs/testing\r\n");
cmd = send(isocket, (void *)buf, strlen(buf), 0);//send directory
recv(isocket, (void *)readBuf, MAX_LENGTH, 0);
NSLog(@"response: %s",readBuf); //read response
strcpy(buf, "TYPE I\r\n");
cmd = send(isocket, (void *)buf, strlen(buf), 0);//set transfer type
recv(isocket, (void *)readBuf, MAX_LENGTH, 0);
NSLog(@"response: %s",readBuf); //read response
strcpy(buf, "PASV\r\n");
cmd = send(isocket, (void *)buf, strlen(buf), 0);//set transfer mode to passive
recv(isocket, (void *)readBuf, MAX_LENGTH, 0);
NSLog(@"response: %s",readBuf); //read response
NSString *pasvResponse = [NSString stringWithFormat:@"%s",readBuf];
strcpy(buf, "STOR mmov.jpeg\r\n");
cmd = send(isocket, (void *)buf, strlen(buf), 0);//start tranfering files
pasvResponse = [pasvResponse stringByReplacingOccurrencesOfString:@"227 Entering Passive Mode (" withString:@""];
pasvResponse = [pasvResponse stringByReplacingOccurrencesOfString:@")." withString:@""];
pasvResponse = [pasvResponse stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSArray *matches = [pasvResponse componentsSeparatedByString:@","];
NSString *ip = nil;
int port = 0;
if([matches count] > 2) {
ip = [NSString stringWithFormat:@"%@.%@.%@.%@",matches[0],matches[1],matches[2],matches[3]];
port = ([matches[4] intValue] * 256) + ([matches[5] intValue]);
}
if(port != 0 && ip != nil) {
struct sockaddr_in servaddr_pasv;
memset(&servaddr_pasv, 0, sizeof(servaddr_pasv));
int isocket_pasv = socket(AF_INET,SOCK_STREAM,0);
servaddr_pasv.sin_family = AF_INET;
servaddr_pasv.sin_addr.s_addr = inet_addr([ip UTF8String]);
servaddr_pasv.sin_port = htons(port);
int res_pasv = connect(isocket_pasv, (struct sockaddr_in *)&servaddr_pasv, sizeof(servaddr_pasv));
if(res_pasv < 0) {
NSLog(@"problem connecting to server passv");
}
NSInputStream *input = [NSInputStream inputStreamWithFileAtPath:@"/Users/myMac/Desktop/limitation.jpeg"];
[input open];
int i= 0;
while(1) {
if([input hasBytesAvailable]) {
i++;
uint8_t buffer[1024];
long res = [input read:buffer maxLength:1024];
NSLog(@"Bytes Read: %ld",res);
if(res != 0) {
long bytesSent = write(isocket_pasv, buffer, sizeof(buffer));
NSLog(@"%d Bytes Transfered: %ld",i,bytesSent);
// sleep(1);
}
if(res == 0) {
break;
}
}
}
[input close];
NSLog(@"bytes write completed");
close(isocket_pasv);
}
close(isocket);
任何帮助提前致谢。
答案 0 :(得分:4)
您无法保证可以一次性卸载整个缓冲区。在转移所有数据之前,您必须循环写入。您还应检查write返回的错误,它可能是您捕获各种网络相关事件以及更典型的O / S写入错误的地方。
答案 1 :(得分:3)
我猜这是write
来电并不发送你要求它发送的全部内容?这实际上并不出人意料。您只需在新呼叫中将剩余数据发送到write
。
如果要编写所有数据,请使用以下内容:
int write_all(int fd, const void *buffer, const size_t bufsize)
{
size_t to_write = bufsize;
const void *ptr = buffer;
while (to_write > 0)
{
ssize_t written = write(fd, ptr, to_write);
if (written < 0)
return -1;
to_write -= written;
ptr = ((char *) ptr) + written;
}
return bufsize;
}
警告:我从内存中写下以下内容,尚未对其进行测试。