2012-07-02 2 views
1

인터넷을 통해 데이터를 보내는 것에 대해 더 알고 싶습니다. 나는 어디에서나 많이 찾았지만 아무것도 도움이되지 못했습니다 ... 저는 MinGw를 사용하고 있습니다. 개발자 프로그램을 변경해야한다고 말하지 마십시오. 지금까지 내가 발견 한 것으로부터 이것을 만들었습니다 : 그리고 그것은 내 로컬 네트워크에만 유용합니다. 아무도 내가 인터넷을 통해서만 똑같은 일을 할 수있는 방법을 말해 줄 수 있습니까? 반응하지만, 난 그냥 그래서 난 인터넷을 사용할 수 변경해야합니다 코드의 어떤 부분 물었을 때 당신이 읽고 나에게 많은 것을 준 모든 사람에게C++ 인터넷 소켓

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; 
      } 
     } 
    } 
} 

감사합니다. 분명히 나는 ​​거기에 쓰여진 것의 절반을 이해할 수 없다. 아직도 아무것도 도움이되지 않았습니다.

+0

해당 파일의 내용을 게시 할 수 있습니까? 인터넷에서 임의의 파일을 다운로드하지 않습니다. – Blender

+0

코드 막대에 소스를 넣을 수 있습니까? – user1496857

+0

질문에 코드를 입력하십시오. 경험하는 어려움에 대해 더 자세히 기술하십시오. NAT를 사용하고 있습니까 (아마도 라우터에서). –

답변

0

이해가되지 않는 부분은 무엇입니까? 코드를보고 로컬 소켓에 바인딩 한 다음 클라이언트와 연결합니다. 당신은 인터넷을 통해서도 이것을 할 수 있지만 그 과정에 대해 이해하지 못하는 것은 무엇입니까? 소켓 코드를 작성하기 전에 TCP/IP의 기초를 배우기 시작할 필요가 있습니다. 그것은 우주 왕복선을 건설하여 공학을 시작하려는 것과 같습니다.

+0

다음 u는 코드를 수정하거나 적어도 "TCP/IP의 기초 학습을 시작"이라고 말해 줄 수있다. – user1496857

+0

그건 내가 아니다. 당신의 주장을 이해할 수는 없지만 이것이 OP를 도울 것이라고는 생각하지 않습니다. 그러나 소스 –

+0

@ user1496857을 게시 해 주셔서 감사합니다. 내 대답의 링크에있는 문서를 읽어야합니다. 당신이 아직 알지 못했던 개념을 접하게된다면, 좋은 점을 알게 될 것입니다. –

2

인터넷을 통해 소켓을 사용하고 NAT를 포함한 모든 네트워크 설정에서 응용 프로그램을 사용할 수있게하려면 TCP 홀 펀치 기술 (또는 UDP 홀 펀칭이 적합 할 수도 있음)을 사용해야합니다. 귀하의 접근 방식이 작동하지 않는 것 같아요 왜냐하면 소켓 연결에 실패하기 때문에 귀하의 종점 사이에 일부 NAT가 있기 때문입니다.

NAT에 대한 조사를 제안합니다. Peer-to-Peer Communication Across Network Address Translators

그리고 this discussion here on SO

+0

홀 펀칭은 까다 롭습니다. 내가 말하길 - NAT에서 명시 적으로 열린 포트를 수행하십시오. 즉, 일단 OP가 NAT라고 알고 있다면. –

+0

그는 다른 엔드 포인트에 대한 정보를 제공하지 않았으므로 아마도 충분하지 않을 수 있습니다. 당신 말이 맞아요, 까다 롭습니다. 심지어 TCP/IP에 대한 지식이 있다면 –

0

인터넷에서 볼 수의 서비스를 호스팅 할 수있는 기능이있어 인터넷 연결 유형에 매우 의존한다. NAT 뒤에 있다면 NAT 포트 포워딩을 설정해야합니다. IP 주소가 동적 인 경우 공개적으로 사용 가능한 IP 주소 (http://www.whatismyip.com/)를 알아야합니다.

+0

OP가 내 대답에서 볼 수 있듯이 ... –

+0

나는 거의 모든 PC에서 프로그램을 실행하고 싶다. 포트 포워드가 있다고하더라도, 그렇지 않더라도 말이다. – user1496857

+0

@ user1496857 그것은 칭찬할만한 목표이지만, 당신이 그 사실을 알지 못한다는 것이 아주 분명합니다. 제발 그걸 개인적으로 받아들이지 마세요. 그리고 그것은 많은 지식을 가지고 있습니다. 하나의 SO 답변 이상은 합리적으로 적합합니다. –