2014-07-03 38 views
9

我想通過UDP發送一個字符串:"Jane Doe"到內部網絡IP 192.168.0.4到端口9000。我通過Java通過UDP和TCP完成了這麼多次,但是現在我必須用標準C++庫來完成這項工作,而且我找不到任何只有人們無法使其工作的樣本。在C++中通過UDP發送字符串

我知道我必須將"Jane Doe"編碼爲字節數組,然後只需打開套接字,將其打包成數據報併發送。

C++不是我的第一語言,這是我找不到的代碼的一小部分,我選擇了UDP,因爲它總是比TCP簡單得多。

+1

我可能會使用升壓ASIO。如果我不能使用它(不管出於什麼原因),我可能會使用我在[CodeReview]上的一個答案(http://codereview.stackexchange.com/a/46354/489)中發佈的類。就目前而言,該代碼是Windows專用的,但幾乎只有Windows特有的部分是'socket_user'類和'#pragma comment lib'行(我認爲這些是唯一的部分,但我沒有測試過確定)。 –

+0

@Yoda請選擇一個答案 –

回答

10

下面是一些示例Unix代碼。

如果這是Windows程序設計:

  • 「襪子」 應該是SOCKET,而不是int類型。
  • 使用closesocket而不是close
  • #include <winsock2.h>,而不是所有的UNIX頭

#include <sys/types.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <unistd.h> 
#include <arpa/inet.h> 
#include <netdb.h> 
#include <memory.h> 
#include <ifaddrs.h> 
#include <net/if.h> 
#include <errno.h> 
#include <stdlib.h> 
#include <iostream> 


int resolvehelper(const char* hostname, int family, const char* service, sockaddr_storage* pAddr) 
{ 
    int result; 
    addrinfo* result_list = NULL; 
    addrinfo hints = {}; 
    hints.ai_family = family; 
    hints.ai_socktype = SOCK_DGRAM; // without this flag, getaddrinfo will return 3x the number of addresses (one for each socket type). 
    result = getaddrinfo(hostname, service, &hints, &result_list); 
    if (result == 0) 
    { 
     //ASSERT(result_list->ai_addrlen <= sizeof(sockaddr_in)); 
     memcpy(pAddr, result_list->ai_addr, result_list->ai_addrlen); 
     freeaddrinfo(result_list); 
    } 

    return result; 
} 


int main() 
{ 
    int result = 0; 
    int sock = socket(AF_INET, SOCK_DGRAM, 0); 

    char szIP[100]; 

    sockaddr_in addrListen = {}; // zero-int, sin_port is 0, which picks a random port for bind. 
    addrListen.sin_family = AF_INET; 
    result = bind(sock, (sockaddr*)&addrListen, sizeof(addrListen)); 
    if (result == -1) 
    { 
     int lasterror = errno; 
     std::cout << "error: " << lasterror; 
     exit(1); 
    } 


    sockaddr_storage addrDest = {}; 
    result = resolvehelper("192.168.0.4", AF_INET, "9000", &addrDest); 
    if (result != 0) 
    { 
     int lasterror = errno; 
     std::cout << "error: " << lasterror; 
     exit(1); 
    } 

    const char* msg = "Jane Doe"; 
    size_t msg_length = strlen(msg); 

    result = sendto(sock, msg, msg_length, 0, (sockaddr*)&addrDest, sizeof(addrDest)); 

    std::cout << result << " bytes sent" << std::endl; 

    return 0; 

} 
+0

@black它證明我的觀點沒有地方,至少很容易找到樣品和技術,以供參考。 – Yoda

+2

@black - 今天有點挑剔不是我們嗎?如果這個答案完全錯誤或者會導致OP到一個糟糕的地方,你只應該回答一個答案。因爲您不喜歡編碼風格,因此不需要進行下調。如果你認爲你有一個更好的方法來回答OP的問題,那麼一定要發表一個答案。我甚至可能自己高興起來。我確實刪除了答案中的標題,以使其更加簡潔。 – selbie

+0

@selbie明確指出:「如果您看到錯誤信息,請將其投票。」老實說,我以爲您從某處複製了代碼,因爲它沒有附帶任何文檔。此外,它確實包含了一些錯誤(實際上它不起作用):'sendto'需要6個參數,而不是4個。最後,從字符串文字到'char *'的轉換被棄用和不安全。 – edmz

10

這是很容易做到,如果你願意使用Boost庫。

這裏是代碼片段

#include "boost/asio.hpp" 
using namespace boost::asio; 

... 

io_service io_service; 
ip::udp::socket socket(io_service); 
ip::udp::endpoint remote_endpoint; 

socket.open(ip::udp::v4()); 

remote_endpoint = ip::udp::endpoint(ip::address::from_string("192.168.0.4"), 9000); 

boost::system::error_code err; 
socket.send_to(buffer("Jane Doe", 8), remote_endpoint, 0, err); 

socket.close(); 
+0

不應該緩衝區大小爲9?包括'\ 0'? –

+0

如果您不想要字符串文字,則可以將字符放入:IPv4地址需要4個字節,其值介於0-255(含)之間。我們都知道2^8 = 256個可能的組合,8位= 1個字節 – dGRAMOP