Создать P2P-соединение через Интернет с помощью winsockets
БОЛЬШОЕ РЕДАКТИРОВАНИЕ
так что, очевидно, мой вопрос был не так хорош (судя по двум отрицательным голосам и двум заключительным запросам), поэтому я решил полностью переписать его, а также предоставить MCVE, как я надеюсь. Надеюсь, в этот раз я справился лучше.
объяснение
Поэтому я хочу создать простую программу совместного использования экрана, такую как Teamviewer, но только с возможностью совместного использования экрана, чтобы программа была быстрой и простой. Для этой цели я хочу использовать winsocket2 из winapi. Я хотел начать с сетевой части и подумать о фактической съемке экрана позже. Я создал небольшой прототип, который создает два сокета (клиент и сервер), которые соединяются через локальный хост и могут отправлять и получать данные до сих пор. Теперь я хочу установить связи через Интернет. Я думал об этом следующим образом:
- Программа запускается и проверяет свой общедоступный IP-адрес, через который он может быть доступен через Интернет, и запускает сервер, связанный с этим IP-адресом и портом (возможно, создает идентификатор IP-адреса и порта или чего-то еще)
- Теперь пользователь может передать этот IP (или ID) другому лицу с другим клиентом, который затем может вставить его в программу (и, возможно, ввести пароль сеанса, как Teamviewer), который затем подключается к первой программе и может получать данные экрана
- Я хочу сделать это без сервера-посредника, поэтому я думаю, что это будет называться P2P
Я довольно неопытен с сетевыми решениями и только начал изучать, так что я мало что знаю об этом. Я хотел создать эту программу для образовательных целей, а также функциональность, которую она предоставляет.
Эта проблема
Теперь у меня есть теория, но нет практической части. Я не знаю, как получить этот публичный IP-адрес. Я провел некоторое исследование и выяснил, что винапи не может найти его локально. Я также узнал, что сервер, конечно, знает мой IP, когда я подключаюсь к нему, и поэтому я мог бы использовать службу в качестве этой проверки ip, но я действительно не хочу полагаться на неофициальные проекты, где я не знаю, разрешено ли мне использовать его в моем проекте и как долго они будут жить.
О чем я думал
Так что я задавался вопросом, есть ли сервисы, которые можно бесплатно использовать для этой цели, например, Google или что-то. Я также немного прочитал о DNS и подумал, могу ли я использовать Google DNS для этой цели. Моей последней попыткой было бы настроить небольшой сервер на бесплатной службе веб-хостинга и написать на нем небольшое приложение, к которому я мог бы подключиться и получить общедоступный IP-адрес, но, возможно, это было бы безуспешно.
Вопрос
Я пытаюсь задать четкий вопрос: я на правильном пути с одной из моих попыток решения или есть что-то, что я полностью упускаю?
Код
так как был запрос на MCVE, я попытался написать немного кода, чтобы показать, чего я хочу достичь и как я это сделаю, я надеюсь, что это ясно и понятно:
#include <iostream>
#include <winsock2.h>
#include <windows.h>
ULONG getPublicAddr() {
/* This is what i came up with so far this is just non working code to show what i want */
SOCKET i_ask_a_server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in addr_of_server_to_ask;
addr_of_server_to_ask.sin_family = AF_INET;
addr_of_server_to_ask.sin_port = htons(53); /* DNS port as i have read */
addr_of_server_to_ask.sin_addr.s_addr = inet_addr("8.8.8.8"); /* This is where i think i need to put an ip of a server i can ask for my IP i read a bit around and think the google
DNS might be what i was looking for */
connect(i_ask_a_server, (sockaddr *) &addr_of_server_to_ask, sizeof(sockaddr_in));
/* Now send a request and receive the result or something... */
closesocket(i_ask_a_server);
return inet_addr("127.0.0.1"); /* <- the public IP i would receive. For now just with a dummy */
}
int main () {
ULONG publicAddr = getPublicAddr();
SOCKET server;
server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
/* Check for valid socket here */
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(10000); /* Or whatever port */
serverAddr.sin_addr.s_addr = publicAddr; /* <- here i would need to add the public address to create a connection over the Internet */
bind(server, (sockaddr *) &serverAddr, sizeof(sockaddr_in)); /* Bind the server to the IP and port and listen for connections over the Internet */
/* Also check for valid binding */
listen(server, 1);
sockaddr_in clientAddr;
int clientAddrLen = sizeof(sockaddr_in);
/* Maybe do some checking before blindly accept the connection */
SOCKET client = accept(server, (sockaddr *) & clientAddr, &clientAddrLen);
/* You know the procedure... */
std::cout << "Connected to client: " << inet_ntoa(clientAddr.sin_addr) << std::endl; /* I thought of something like this for a little webserver that then sends this result back to the application because that would be the public IP as i understood */
CHAR buffer[4096]; /* Just about enough for whatever purpose */
int result;
while (true) {
result = recv(server, buffer, sizeof(buffer), 0); /* receive data */
if (result <= 0) break; /* If no data could be received or connection was lost break. Maybe do error checking in before */
std::cout << "Received " << result << " B" << std::endl;
}
closesocket(client);
closesocket(server);
return 0;
}