【问题标题】:Socket over internet in C++C ++中的互联网套接字
【发布时间】:2012-07-02 18:55:14
【问题描述】:

我想了解更多关于通过互联网发送数据的信息。 我一直在到处搜索,但没有任何帮助...... 我正在使用 MinGw,请不要说我必须更改我的开发人员程序。 到目前为止,我根据我的发现做了这个: 它工作得很好,但只适用于我的本地网络。谁能告诉我如何只通过互联网做同样的事情?

using namespace std;
#pragma once
#include <iostream>
#include "WinSock2.h"
const int STRLEN = 256;

class Socket
{
    protected:
        WSADATA wsaData;
        SOCKET mySocket;
        SOCKET myBackup;
        SOCKET acceptSocket;
        sockaddr_in myAddress;
    public:
        Socket();
        ~Socket();
        bool SendData( char* );
        bool RecvData( char*, int );
        void CloseConnection();
        void GetAndSendMessage();
};

class ServerSocket : public Socket
{
    public:
        void Listen();
        void Bind( int port );
        void StartHosting( int port );
};

class ClientSocket : public Socket
{
    public:
        void ConnectToServer( const char *ipAddress, int port );
};


Socket::Socket()
{
    if( WSAStartup( MAKEWORD(2, 2), &wsaData ) != NO_ERROR )
    {
        cerr<<"Socket Initialization: Error with WSAStartup\n";
        system("pause");
        WSACleanup();
        exit(10);
    }

    //Create a socket
    mySocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );

    if ( mySocket == INVALID_SOCKET )
    {
        cerr<<"Socket Initialization: Error creating socket"<<endl;
        system("pause");
        WSACleanup();
        exit(11);
    }

    myBackup = mySocket;
}

Socket::~Socket()
{
    WSACleanup();
}

bool Socket::SendData( char *buffer )
{
    send( mySocket, buffer, strlen( buffer ), 0 );
    return true;
}

bool Socket::RecvData( char *buffer, int size )
{
    int i = recv( mySocket, buffer, size, 0 );
    buffer[i] = '\0';
    return true;
}

void Socket::CloseConnection()
{
    //cout<<"CLOSE CONNECTION"<<endl;
    closesocket( mySocket );
    mySocket = myBackup;
}

void Socket::GetAndSendMessage()
{
    char message[STRLEN];
    cin.ignore();//without this, it gets the return char from the last cin and ignores the following one!
    cout<<"Send > ";
    cin.get( message, STRLEN );
    SendData( message );
}

void ServerSocket::StartHosting( int port )
{
     Bind( port );
     Listen();
}

void ServerSocket::Listen()
{
    //cout<<"LISTEN FOR CLIENT..."<<endl;

    if ( listen ( mySocket, 1 ) == SOCKET_ERROR )
    {
        cerr<<"ServerSocket: Error listening on socket\n";
        system("pause");
        WSACleanup();
        exit(15);
    }

    //cout<<"ACCEPT CONNECTION..."<<endl;

    acceptSocket = accept( myBackup, NULL, NULL );
    while ( acceptSocket == SOCKET_ERROR )
    {
        acceptSocket = accept( myBackup, NULL, NULL );
    }
    mySocket = acceptSocket;
}

void ServerSocket::Bind( int port )
{
    myAddress.sin_family = AF_INET;
    myAddress.sin_addr.s_addr = inet_addr( "0.0.0.0" );
    myAddress.sin_port = htons( port );

    //cout<<"BIND TO PORT "<<port<<endl;

    if ( bind ( mySocket, (SOCKADDR*) &myAddress, sizeof( myAddress) ) == SOCKET_ERROR )
    {
        cerr<<"ServerSocket: Failed to connect\n";
        system("pause");
        WSACleanup();
        exit(14);
    }
}

void ClientSocket::ConnectToServer( const char *ipAddress, int port )
{
    myAddress.sin_family = AF_INET;
    myAddress.sin_addr.s_addr = inet_addr( ipAddress );
    myAddress.sin_port = htons( port );

    //cout<<"CONNECTED"<<endl;

    if ( connect( mySocket, (SOCKADDR*) &myAddress, sizeof( myAddress ) ) == SOCKET_ERROR )
    {
        cerr<<"ClientSocket: Failed to connect\n";
        system("pause");
        WSACleanup();
        exit(13);
    } 
}

int main()
{
    int choice;
    int port = 666;
    //char *ipAddress = "127.0.0.1";
    string ipAddress;
    bool done = false;
    char recMessage[STRLEN];
    char sendMessage[STRLEN];
    cout<<"1) Host server"<<endl;
    cout<<"2) Join server"<<endl;
    cout<<"3) Quit"<<endl;
    cin>>choice;
    if ( choice == 3 )
        exit(0);
    else if ( choice == 2 )
    {
        //Client
        cout<<"Enter an IP address, 127.0.0.1 is the loopback address"<<endl;
        cin>>ipAddress;
        ClientSocket sockClient;
        cout<<"ATTEMPTING TO CONNECT..."<<endl;
        sockClient.ConnectToServer( ipAddress.c_str(), port );
        //Connected
        while ( !done )
        {     
            sockClient.GetAndSendMessage();
            cout<<"\t--WAIT--"<<endl;
            sockClient.RecvData( recMessage, STRLEN );
            cout<<"Recv > "<<recMessage<<endl;
            if ( strcmp( recMessage, "end" ) == 0 ||
                        strcmp( sendMessage, "end" ) == 0 )
            {
                done = true;
            }
        }
        sockClient.CloseConnection();
    }
    else if ( choice == 1 )
    {
        //SERVER
        ServerSocket sockServer;
        cout<<"HOSTING..."<<endl;
        sockServer.StartHosting( port );
        //sockServer.StartHosting( port );
        //Connected
        while ( !done )
        {
            cout<<"\t--WAIT--"<<endl;
            sockServer.RecvData( recMessage, STRLEN );
            cout<<"Recv > "<<recMessage<<endl;
            sockServer.GetAndSendMessage();
            if ( strcmp( recMessage, "end" ) == 0 || strcmp( sendMessage, "end" ) == 0 )
            {
                done = true;
            }
        }
    }
}

感谢所有回复的人,但是当我问应该更改代码的哪一部分以便我可以使用互联网时,您给了我很多阅读。显然我无法理解那里写的一半。仍然没有任何帮助。

【问题讨论】:

  • 你能把那个文件里的内容贴出来吗?我不会从互联网上下载随机文件。
  • 如何将源代码放在代码栏中?
  • 请在您的问题中提供代码。请写更多关于您遇到的困难。您是否在使用 NAT(可能在您的路由器中)。
  • 编辑问题,粘贴源代码,突出显示,然后按Code按钮(或CTRL-K)。
  • 我冒昧地更新了他的帖子以包含该站点的代码...

标签: c++ sockets client-server data-transfer


【解决方案1】:

如果您想在 Internet 上使用套接字,并且希望您的应用程序可以在包括 NAT 在内的所有网络设置中使用,您将不得不使用一种称为 TCP Holepunch 的技术(或者 UDP 打孔也可能适用)。我认为你的方法不起作用 因为端点之间有一些 NAT,所以套接字连接失败。

我建议对 NAT 进行调查。 Peer-to-Peer Communication Across Network Address Translators

还有this discussion here on SO

【讨论】:

  • 打孔很棘手。我说 - 只需在 NAT 中明确打开端口即可。也就是说,一旦 OP 知道它是一个 NAT。
  • 而且由于他没有提供有关他的不同端点的信息,也许这还不够。你是对的,这很棘手。即使对 TCP/IP 有一定的了解
【解决方案2】:

什么是你不明白的?我看到了代码,它绑定到本地套接字,然后你用客户端连接到它。您也可以通过 Internet 执行此操作,但是您不了解该过程的哪些内容?恐怕在尝试编写套接字代码之前,您可能需要开始学习 TCP/IP 的基础知识。这就像尝试通过建造航天飞机开始学习工程学。

【讨论】:

  • 你能不能修改一下代码或者至少告诉我从哪里“开始学习 TCP/IP 的基础知识”
  • 并不是我不能理解你的论点,但我不相信这会对 OP 有所帮助。但是感谢您发布源代码
  • @user1496857 您应该阅读我答案中链接中的文档。如果您遇到您不知道的概念,您将有很好的起点开始学习
  • @user1496857 - 在我看来,根据我的经验,如果你想学习 TCP/IP 的基础知识,你需要一本教科书。你不会仅仅通过修修补补来学习这一点。是的,学习涉及修修补补,但这两者并不相同。
  • 我同意,如果你真的想知道你在做什么,你真的需要一本关于 TCP/IP 的书。您可能可以通过修补来破解某些东西,但是您将不知道发生了什么,如果您不知道自己在做什么,就不应该编写套接字代码。
【解决方案3】:

托管从 Internet 可见的服务的能力在很大程度上取决于您拥有的 Internet 连接类型。如果您在 NAT 后面,则需要设置 NAT 端口转发。如果您的 IP 地址是动态的,则需要知道您的公开 IP 地址(试试http://www.whatismyip.com/)。

【讨论】:

  • 我希望该程序几乎可以在每台电脑上运行,即使他们有端口转发,即使他们没有。
  • @user1496857 这是一个值得称赞的目标,但很明显您不具备这方面的知识。请不要把它当作个人,我们都曾在某个时候去过那里。问题是,这是很多知识 - 不仅仅是一个 SO 答案可以合理地适合。
猜你喜欢
  • 2013-04-12
  • 1970-01-01
  • 1970-01-01
  • 2016-05-24
  • 2011-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-08
相关资源
最近更新 更多