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

一度にバッファ全体をオフロードできるとは限りません。すべてのデータが転送されるまで、上書きをループする必要があります。書き込みによって返されるエラーも確認する必要があります。これは、あらゆる種類のネットワーク関連のイベントや、より一般的な 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 に答える