1

如果将写入功能放置在没有睡眠的循环中,我将面临写入功能无法正常工作的问题。我想要实现的是将文件从本地机器传输到远程 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);

任何帮助提前谢谢。

4

2 回答 2

4

您不能保证可以一次性卸载整个缓冲区。您必须循环写入,直到所有数据都传输完毕。您还应该检查 write 返回的错误,它可能是您捕获各种网络相关事件以及更典型的 O/S 写入错误的地方。

于 2013-01-22T13:59:23.890 回答
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;
}

警告:我从记忆中写了以下内容,尚未测试过。

于 2013-01-22T13:59:21.293 回答