簡體   English   中英

如何使用套接字編程在兩台遠程機器之間發送數據?

[英]How to send data between two remote machines using socket programming?

我正在嘗試將數據從一台遠程計算機 (Ubuntu) 發送到我的家用計算機 (High Sierra)。 我讀過對夫婦問題,在這里左右,但他們似乎不給解決我的問題。 我使用ssh連接到遠程計算機,並在兩台計算機上創建並成功編譯了以下程序。

客戶端

#include <iostream>
#include <string>

#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>


int main(int argc, char* argv[])
{
    std::string address = argv[1];
    int port = 38473;
    int success;

    // http://man7.org/linux/man-pages/man2/socket.2.html
    int server_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (server_socket == -1)
        return errno;

    sockaddr_in socket_address{};
    socket_address.sin_family = AF_INET;
    socket_address.sin_port = htons(port);  // htons - Host to Network Short. Flip endianness to match machine.
    success = inet_pton(AF_INET, address.c_str(), &socket_address.sin_addr);  // Pointer (to String) to Number.
    if (success <= 0)
        return errno;

    success = connect(server_socket, (sockaddr*)&socket_address, sizeof(socket_address));
    if (success == -1)
        return errno;

    std::cout << "Connected" << std::endl;
    for (int i = 0; i < 10; ++i)
        write(server_socket, "Hello!\n", 7);
}

服務器.cpp

#include <iostream>
#include <string>

#include <cstring>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>


int main(int argc, char* argv[])
{
    std::string address = "127.0.0.1";
    int port = 38473;
    int success;

    // http://man7.org/linux/man-pages/man2/socket.2.html
    int listen_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_socket == -1)
        return errno;

    sockaddr_in socket_address{};
    socket_address.sin_family = AF_INET;
    socket_address.sin_port = htons(port);  // htons - Host to Network Short. Flip endianness to match machine.
    success = inet_pton(AF_INET, address.c_str(), &socket_address.sin_addr);  // Pointer (to String) to Number.
    if (success <= 0)
        return errno;

    // http://man7.org/linux/man-pages/man2/bind.2.html
    success = bind(listen_socket, (sockaddr*)&socket_address, sizeof(socket_address));
    if (success == -1)
        return errno;

    // http://man7.org/linux/man-pages/man2/listen.2.html
    success = listen(listen_socket, 10);
    if (success == -1)
        return errno;

    sockaddr_in client_address;
    socklen_t   client_address_size = sizeof(client_address);
    int client_socket = accept(listen_socket, (sockaddr*)&client_address, &client_address_size);
    if (client_socket == -1)
        return errno;

    close(listen_socket);

    size_t buffer_size = 4096;
    char buffer[buffer_size];
    ssize_t bytes_received;

    std::cout << "Connected" << std::endl;
    while (true)
    {
        memset(buffer, 0, buffer_size);
        // http://man7.org/linux/man-pages/man2/recvmsg.2.html

        if ((bytes_received = read(client_socket, buffer, buffer_size)) <= 0)
            return 0;
        std::cout << "Message: " << buffer << std::endl;
    }
}

當在同一台機器上運行這兩個程序時(客戶端可執行文件在命令行中將 127.0.0.1 作為參數),它可以完美運行並發送數據。 嘗試將本地計算機作為服務器運行並從遠程運行 client.cpp 時,我收到錯誤代碼 111(連接被拒絕)。

在閱讀了各種教程/博客/帖子后,這似乎是:

  1. 該端口當前未在偵聽。
  2. 防火牆阻止連接。

我嘗試通過執行以下操作來解決此問題。

該端口當前未在偵聽。

當遠程機器試圖連接到我的公共 IP 地址時,我必須將端口轉發到我的本地機器。 我登錄到我的路由器並添加了一個條目以將端口 38473 轉發到我的私有 IP 地址。 這個端口是隨機選擇的,因為iana將其標記為未分配,而且它非常大。 由於我可以在一台機器上運行這兩個程序時發送數據,因此我認為端口不是問題。

端口轉發表

防火牆阻止連接。

我確保禁用本地計算機的防火牆(在系統偏好設置 -> 安全和隱私 -> 防火牆中),並在我的路由器中輸入一個條目,允許通過端口 38473 來自遠程計算機的消息(使用其公共 IP 地址)。

防火牆配置

我似乎仍然無法連接。 我運行了Wireshark ,可以看到遙控器確實發送了 SYN 請求,但得到了 [RST, ACK] 作為回報。 RST 標志似乎是防火牆終止連接的一種方式,但考慮到我之前的上述配置,我不明白為什么會這樣做。

Wireshark 輸出

我究竟做錯了什么?

調整您的服務器代碼以在計算機上偵聽您感興趣的以太網卡的 IP,或者:

   serv_addr.sin_family = AF_INET;
   serv_addr.sin_addr.s_addr = INADDR_ANY;
   serv_addr.sin_port = htons(portno);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM