2011-06-19 131 views
0

我正在做一些iPhone套接字測試。這是代碼(它的工作原理):第二個參數CFSocketSendData函數問題

struct sockaddr_in destinationAddress; 
socklen_t sockaddr_destaddr_len = sizeof(destinationAddress); 
CFSocketError socket_error = 0; 

CFSocketRef socket = CFSocketCreate(kCFAllocatorDefault, 
            AF_INET, 
            SOCK_STREAM, 
            IPPROTO_TCP, 
            kCFSocketNoCallBack, 
            NULL, 
            NULL); 

if (!socket) { 
    NSLog(@"CfSocketCreate Failed"); 
} 

memset(&destinationAddress, 0, sockaddr_destaddr_len); 
destinationAddress.sin_len = sockaddr_destaddr_len; 
destinationAddress.sin_family = AF_INET; 
destinationAddress.sin_port = htons(23678); 
destinationAddress.sin_addr.s_addr = inet_addr("127.0.0.1"); 

NSData *destinationAddressData = [NSData dataWithBytes:&destinationAddress length:sizeof(destinationAddress)]; 

NSString *message = @"data to send, new line\n"; 
NSData *message_data = [message dataUsingEncoding:NSUTF8StringEncoding]; 

CFSocketConnectToAddress(socket, (CFDataRef) destinationAddressData, 10); 
socket_error = CFSocketSendData (socket, NULL, (CFDataRef) message_data, 10); 

// show the status 
if(socket_error < 0){ 
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Socket situation" 
                message:@"Socket error" 
                delegate:self 
              cancelButtonTitle:@"Ok" 
              otherButtonTitles:nil]; 
    [alert show]; 
    [alert release]; 
} 

所以,首先我打開連接到另一個套接字(我的日誌服務器)。其次,我使用2nd NULL參數通過CFSockectSendData發送數據,以便使用之前打開的連接。問題是當我嘗試直接通過使用CFSocketSendData函數發送數據,而不使用CFSocket CFSocketConnectToAddress函數。代碼變爲:

struct sockaddr_in destinationAddress; 
socklen_t sockaddr_destaddr_len = sizeof(destinationAddress); 
CFSocketError socket_error = 0; 

CFSocketRef socket = CFSocketCreate(kCFAllocatorDefault, 
            AF_INET, 
            SOCK_STREAM, 
            IPPROTO_TCP, 
            kCFSocketNoCallBack, 
            NULL, 
            NULL); 

if (!socket) { 
    NSLog(@"CfSocketCreate Failed"); 
} 

memset(&destinationAddress, 0, sockaddr_destaddr_len); 
destinationAddress.sin_len = sockaddr_destaddr_len; 
destinationAddress.sin_family = AF_INET; 
destinationAddress.sin_port = htons(23678); 
destinationAddress.sin_addr.s_addr = inet_addr("127.0.0.1"); 

NSData *destinationAddressData = [NSData dataWithBytes:&destinationAddress length:sizeof(destinationAddress)]; 

NSString *message = @"data to send, new line\n"; 
NSData *message_data = [message dataUsingEncoding:NSUTF8StringEncoding]; 

socket_error = CFSocketSendData (socket, (CFDataRef) destinationAddressData, (CFDataRef) message_data, 10); 

// show the status 
if(socket_error < 0){ 
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Socket situation" 
                message:@"Socket error" 
                delegate:self 
              cancelButtonTitle:@"Ok" 
              otherButtonTitles:nil]; 
    [alert show]; 
    [alert release]; 
} 

在這種情況下,我收集CFSocketSendData錯誤,並顯示警報視圖。什麼是錯誤? 只是我刪除了CFSocketConnectToAddress函數,因爲具有第二個參數非NULL的CFSocketSendData應該能夠連接到一個特定的地址。

回答

0

No. TCP是面向連接的協議。您必須先建立連接,然後才能發送任何數據。它沒有爲你「連接到一個特定的地址」,因爲能夠指定一個目的地址的要點是能夠重複使用同一個套接字用於多個目的地。如果您使用不同的地址調用CFSocketSendData()會發生什麼?舊的連接會關閉嗎?如果不是,你將如何關閉其中一個連接而不關閉另一個?

如果您改爲使用UDP(指定SOCK_DGRAM而不是SOCK_STREAM),則可以爲每個數據包指定一個不同的地址。當然,請注意使用UDP的多個注意事項(無保證傳送,無論何種流量控制,並且因爲不存在UDP連接等情況,您必須執行自己的「連接管理」)。

在這種情況下,我收集CFSocketSendData錯誤,並顯示警報視圖。什麼是錯誤?

那麼,UIAlertView是怎麼說的?

+0

首先,感謝您的回覆。是的,TCP是一種三向握手階段的面向連接的協議。蘋果文檔報告(對於CFSocketSendData的第二個參數):「地址,作爲struct sockaddr存儲在一個CFData對象中,向其發送數據內容。如果爲NULL,則將數據發送到其所在的地址已經連接」。我認爲CFSocketSendData可以對TCP協議進行連接。如果我在建立連接後用另一個地址調用CFSocketSendData,它將返回一個錯誤。 – bitfox

+0

AlertView顯示:從您的代碼中可以看到套接字錯誤。但是,返回的錯誤代碼爲-1,意味着(來自蘋果文檔):「套接字操作失敗」。最後,連接可以通過使用CFSocketInvalidate來關閉。 – bitfox

+1

我的不好; CFSocket似乎沒有任何錯誤報告。 UDP本身沒有「連接」(「連接」UDP套接字只是設置其默認地址)。文檔沒有說它建立了連接;它只是說,如果連接建立,數據將轉到該地址。 TCP不支持將數據發送到您尚未連接的端點。此外,CFSocketSendData的代碼清楚地調用send()或sendto(),具體取決於您是否指定了地址:http://www.opensource.apple.com/source/CF/CF-550.42/CFSocket.c –