Я пытаюсь изучить основы сетевого программирования с помощью Winsock2 API. Мне удалось подключиться через IP-адреса локальной сети, но я уже целый день пытаюсь заставить клиента подключиться к моему серверу через его общедоступный IP-адрес.
Я уже настроил переадресацию портов на своем маршрутизаторе и даже использовал Wireshark для отслеживания запросов на подключение клиентов. Я вижу запросы в Wireshark, но он никогда не подключается к серверу, и в итоге я получаю сообщение об ошибке тайм-аута.
Я в растерянности, я ценю любого, кто может указать мне правильное направление!
Это реализация клиента:
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")
#define DEFAULT_PORT //MY PORT
#define DEFAULT_BUFLEN 512
#define SERVER_IPV4 //"MY PUBLIC IP STRING"
int main(int argc, char **argv)
{
//wsaData to hold Winsock dll information
WSADATA wsaData;
WORD wVersionRequired = MAKEWORD(2, 2);
//Attempts to load winsock dll matching required version and fills WSADATA object
int wsaInit = WSAStartup(wVersionRequired, &wsaData);
if(wsaInit != 0)
{
printf("WSAStartup failed with error code: %d\n", wsaInit);
}
//If dll fails to load correct version free winsock dll resources
if(wsaData.wHighVersion != wVersionRequired)
{
printf("No usable version of Winsock.dll found\n");
WSACleanup();
return 1;
}
else
{
printf("Winsock dll 2.2 loaded correctly\n");
}
/**********************Socket Code Here**********************/
SOCKADDR_IN SockAddrIP4;
SockAddrIP4.sin_family = AF_INET;
SockAddrIP4.sin_addr.s_addr = inet_addr(SERVER_IPV4);
SockAddrIP4.sin_port = htons(DEFAULT_PORT);
/**************Create Socket****************/
//INVALID_SOCKET used like NULL
SOCKET ConnectSocket = INVALID_SOCKET;
// TODO(baruch): Only supporting IP_V4
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(ConnectSocket == INVALID_SOCKET)
{
printf("socket() error: %ld\n", WSAGetLastError());
//clean up address info after getaddrinfo function when socket fails
WSACleanup();
return 1;
}
/*****************Connect to socket**************/
int connectResult = connect(ConnectSocket, (SOCKADDR*)&SockAddrIP4, sizeof(SOCKADDR_IN));
if(connectResult == SOCKET_ERROR)
{
printf("Connect failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
}
else
{
printf("Connected with server: %s\n", SERVER_IPV4);
}
if(ConnectSocket == INVALID_SOCKET)
{
printf("Unable to connect with server\n");
WSACleanup();
return 1;
}
/*************END of Socket CODE CLEANUP********/
// TODO(baruch): close socket
WSACleanup();
}
А это сервер:
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")
// TODO(baruch): Only supporting ascii consider Unicode later
#undef UNICODE
#define DEFAULT_PORT //My Port
#define DEFAULT_BUFLEN 512
int main(int argc, char **argv)
{
//wsaData to hold Winsock dll information
WSADATA wsaData;
WORD wVersionRequired = MAKEWORD(2, 2);
int wsaInit = WSAStartup(wVersionRequired, &wsaData);
if(wsaInit != 0)
{
printf("WSAStartup failed with error code: %d\n", wsaInit);
}
//If dll fails to load correct version free winsock dll resources
if(wsaData.wHighVersion != wVersionRequired)
{
printf("No usable version of Winsock.dll found\n");
WSACleanup();
return 1;
}
else
{
printf("Winsock dll 2.2 loaded correctly\n");
}
/**********************Socket Code Here**********************/
/**************Create Socket****************/
SOCKADDR_IN SockAddrIP4;
SockAddrIP4.sin_family = AF_INET;
SockAddrIP4.sin_addr.s_addr = INADDR_ANY;
SockAddrIP4.sin_port = htons(DEFAULT_PORT);
//INVALID_SOCKET used like NULL
SOCKET ListenSocket = INVALID_SOCKET;
// TODO(baruch): Only supporting IP_V4
// Socket for server to listen on for client connections
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(ListenSocket == INVALID_SOCKET)
{
printf("socket() error: %ld\n", WSAGetLastError());
//clean up address info after getaddrinfo function when socket fails
WSACleanup();
return 1;
}
/**************Bind Socket******************/
int bindResult = bind(ListenSocket, (SOCKADDR*)&SockAddrIP4, sizeof(SOCKADDR_IN));
if(bindResult == SOCKET_ERROR)
{
printf("failed to bind with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
/************Listen for Connections**********/
int listenResult = listen(ListenSocket, SOMAXCONN);
if(listenResult == SOCKET_ERROR)
{
printf("Listen failed, error: %d\n", WSAGetLastError() );
WSACleanup();
return 1;
}
else
{
printf("Now listening for client connections...\n");
}
/************Accept and Handle CLient Connections***********/
// TODO(baruch): For testing, only allowing a single client. Eventually need to create a loop to handle all client connections.
SOCKET ClientSocket;
SOCKADDR_IN connectedAddress;
int addressLength = sizeof(connectedAddress);
ClientSocket = accept(ListenSocket, (SOCKADDR *) &connectedAddress, &addressLength);
if(ClientSocket == SOCKET_ERROR)
{
printf("Accept failed, error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
else
{
//inet_ntoa converts ip address to binary format.
char *clientIp = inet_ntoa(connectedAddress.sin_addr);
// TODO(baruch): Make sure this string correctly prints address
printf("Client connection from: %s accepted\n", clientIp);
}
/**********Handle inbound and outbound data**********/
char inBuf[DEFAULT_BUFLEN];
int dataBufLen = DEFAULT_BUFLEN;
int inDataResult, outDataResult;
do
{
inDataResult = recv(ClientSocket, inBuf, dataBufLen, 0);
if(inDataResult > 0)
{
printf("Number of bytes received: %d", inDataResult);
//Confirm to client message received
char confirmReceipt[] = "\nMessage received!\n";
outDataResult =
send(ClientSocket, confirmReceipt, sizeof(confirmReceipt), 0);
if(outDataResult == SOCKET_ERROR)
{
printf("Confirmation message failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
else
{
printf("Confirmation message sent\n");
}
}
else if(inDataResult == 0)
{
printf("Connection closing\n");
}
else
{
printf("Data receipt failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
} while(inDataResult > 0);
//Shutdown sending portion of socket, can still receive data
int shutDownResult = shutdown(ClientSocket, SD_SEND);
if(shutDownResult == SOCKET_ERROR)
{
printf("Shutdown failure, error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
/*************End Socket Code Clean up Winsock dll**********/
closesocket(ClientSocket);
WSACleanup();
}