I am following the Getting Started with WinSock guide (here) from Microsoft.
In my situation I have a java application that act as the client, and a c++ application for the server.
Here is the server code so far:
//all includes
int main()
{
WSADATA wsaData;
int iResult;
SOCKET listenSocket = INVALID_SOCKET;
SOCKET clientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
int iSendResult;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
//Initialization
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
else {
printf("WSAStartup success !\n");
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
//Resolve the server adress and port
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
listenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (listenSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
//Setup the TCP listening socket
iResult = bind(listenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(listenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
iResult = listen(listenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(listenSocket);
WSACleanup();
return 1;
}
clientSocket = accept(listenSocket, NULL, NULL);
if (clientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(listenSocket);
WSACleanup();
return 1;
}
//No longer need server socket
closesocket(listenSocket);
// Receive until the peer shuts down the connection
do {
iResult = recv(clientSocket, recvbuf, recvbuflen, 0);
printf("result : %d", iResult);
//Receive data
if (iResult > 0) {
printf("Bytes received: %d\n", iResult);
printf("Message: %s\n Sending response to client... ", recvbuf);
const char* response = "Hello from key/mouse emulator app server";
iSendResult = send(clientSocket, response, sizeof(char) * (strlen(response)+1), 0);
if (iSendResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(clientSocket);
WSACleanup();
return 1;
}
printf("Bytes sent: %d\n", iSendResult);
}
else if (iResult == 0)
printf("Connection closing...\n");
else {
printf("recv failed with error: %d\n", WSAGetLastError());
closesocket(clientSocket);
WSACleanup();
return 1;
}
} while (iResult > 0);
// shutdown the connection since we're done
iResult = shutdown(clientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(clientSocket);
WSACleanup();
return 1;
}
// cleanup
closesocket(clientSocket);
WSACleanup();
system("PAUSE");
return 0;
}
My understanding was that in the do...while loop it was listening to any incoming data from the client. So I tried to debug to check what kind of values I have in iResult when nothing is sent.
I found out using Visual Studio community 2017 that I could not go further this line :
clientSocket = accept(listenSocket, NULL, NULL);
And it would only go in the do...while when the client sent some data.
So my question is what happens in the program when I reach accept(...) line?
Related
So I wanted to learn more on how the TCP protocol works and started messing with windows sockets (WinSocks2), I managed to write a basic server and client from the Microsoft documentation.
I expected to see a 3-way handshake in Wireshark, and I did but not in the way I imagined, it was actually duplicated (The server sends the same packets as the client back to the client).
So my question is, is this normal, or am I doing something wrong?
Here is my source code of the server:
// This should be placed before #include <Windows.h> if the windows include is used
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <cstdio>
#include <Windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
/// TEST CODE /// REMOVE AFTER TESTING WAS DONE ///
int main()
{
WSADATA wsaData;
int iResult;
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0)
{
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
struct addrinfo* result = NULL, * ptr = NULL, hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the local address and port to be used by the server
iResult = getaddrinfo("0.0.0.0", "1337", &hints, &result);
if (iResult != 0)
{
printf("getaddrinfo failed: %d\n", iResult);
WSACleanup();
return 1;
}
SOCKET ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ListenSocket == INVALID_SOCKET)
{
printf("Error at socket(): %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
}
iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR)
{
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR)
{
printf("Listen failed with error: %ld\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
// Handling pending connections
puts("Waiting for a connection..");
SOCKET ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET)
{
printf("accept failed: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
#define DEFAULT_BUFLEN 512
char recvbuf[DEFAULT_BUFLEN];
int iSendResult;
int recvbuflen = DEFAULT_BUFLEN;
int size =0 ;
// Receive until the peer shuts down the connection
do
{
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (iResult > 0)
{
printf("Bytes received: %d\n", iResult);
size += iResult;
// I thought this was the problem but after I removed it from the code it still was the same.
//
// Echo the buffer back to the sender
//iSendResult = send(ClientSocket, recvbuf, iResult, 0);
/*if (iSendResult == SOCKET_ERROR)
{
printf("send failed: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}*/
//printf("Bytes sent: %d\n", iSendResult);
}
else if (iResult == 0)
printf("Connection closing...\n");
else
{
printf("recv failed: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
}
while (iResult > 0);
recvbuf[size] = 0;
printf("Data received: %s\n", recvbuf);
// Stops responding to requests, still can accept tho
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR)
{
printf("shutdown failed: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
// Close socket, no receiving/sending
closesocket(ClientSocket);
WSACleanup();
}
And here is the client:
// This should be placed before #include <Windows.h> if the windows include is used
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <cstdio>
#include <Windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
/// TEST CODE /// REMOVE AFTER TESTING WAS DONE ///
int main()
{
WSADATA wsaData;
int iResult;
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0)
{
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
struct addrinfo* result = NULL, * ptr = NULL, hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the local address and port to be used by the server
iResult = getaddrinfo("109.xxx.xxx.xxx", "1337", &hints, &result);
if (iResult != 0)
{
printf("getaddrinfo failed: %d\n", iResult);
WSACleanup();
return 1;
}
SOCKET ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET)
{
printf("Error at socket(): %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
}
iResult = connect(ConnectSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR)
{
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
}
// Should really try the next address returned by getaddrinfo
// if the connect call failed
// But for this simple example we just free the resources
// returned by getaddrinfo and print an error message
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET)
{
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
#define DEFAULT_BUFLEN 512
int recvbuflen = DEFAULT_BUFLEN;
const char* sendbuf = "this is a test";
char recvbuf[DEFAULT_BUFLEN];
// Send an initial buffer
iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
if (iResult == SOCKET_ERROR)
{
printf("send failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %ld\n", iResult);
// shutdown the connection for sending since no more data will be sent
// the client can still use the ConnectSocket for receiving data
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR)
{
printf("shutdown failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// Receive data until the server closes the connection
do
{
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if (iResult > 0)
printf("Bytes received: %d\n", iResult);
else if (iResult == 0)
printf("Connection closed\n");
else
printf("recv failed: %d\n", WSAGetLastError());
}
while (iResult > 0);
closesocket(ConnectSocket);
WSACleanup();
}
Here is the packets captured from Wireshark, where the IP address starting with 109.xxx.xxx.xxx is the server:
No, the duplicate packets are not normal. But that is not related to your code. It is more likely an issue with your network setup, or just a side effect of how you are capturing the packets.
Unrelated to the duplicate packets, there are other problems with the code shown.
In your server:
your if (ListenSocket == INVALID_SOCKET) block is missing a return, so if socket() fails then you still call bind() with an invalid SOCKET and are dereferencing an invalid result pointer.
Once you reach your recv() loop, you are never closing the ListenSocket before calling WSACleanup().
your printf() of recvbuf needs to be inside the loop when iResult > 0. And if you are going to null-terminate recvbuf then you need to use recvbuflen-1 when calling recv(), or else you will lose the last byte received. Otherwise, pass iResult as a parameter to printf() so you don't need to null-terminate recvbuf at all.
In your client:
do not use the AI_PASSIVE flag when calling getaddrinfo(). That flag is meant for listening servers, not outbound clients.
your if (ConnectSocket == INVALID_SOCKET) block is missing a return, so if socket() fails then you still call connect() with an invalid SOCKET and are dereferencing an invalid result pointer.
Try this code instead:
server:
// This should be placed before #include <Windows.h> if the windows include is used
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <cstdio>
#include <Windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
/// TEST CODE /// REMOVE AFTER TESTING WAS DONE ///
int main()
{
WSADATA wsaData;
int iResult;
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0)
{
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
struct addrinfo* result = NULL, hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the local address and port to be used by the server
iResult = getaddrinfo(NULL, "1337", &hints, &result);
if (iResult != 0)
{
printf("getaddrinfo failed: %d\n", iResult);
WSACleanup();
return 1;
}
SOCKET ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET)
{
printf("Error at socket(): %d\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR)
{
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR)
{
printf("Listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
// Handling pending connections
puts("Waiting for a connection..");
SOCKET ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET)
{
printf("accept failed: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
#define DEFAULT_BUFLEN 512
char recvbuf[DEFAULT_BUFLEN];
int iSendResult;
// Receive until the peer shuts down the connection
do
{
iResult = recv(ClientSocket, recvbuf, sizeof(recvbuf), 0);
if (iResult > 0)
{
printf("Bytes received: %d\n", iResult);
printf("Data received: %.*s\n", iResult, recvbuf);
// Echo the buffer back to the sender
/*iSendResult = send(ClientSocket, recvbuf, iResult, 0);
if (iSendResult == SOCKET_ERROR)
{
printf("send failed: %d\n", WSAGetLastError());
break;
}
printf("Bytes sent: %d\n", iSendResult);*/
}
else if (iResult == 0)
{
printf("Connection closing...\n");
}
else
{
printf("recv failed: %d\n", WSAGetLastError());
}
}
while (iResult > 0);
// Close socket, no receiving/sending
shutdown(ClientSocket, SD_BOTH);
closesocket(ClientSocket);
WSACleanup();
return 0;
}
client:
// This should be placed before #include <Windows.h> if the windows include is used
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <cstdio>
#include <Windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
/// TEST CODE /// REMOVE AFTER TESTING WAS DONE ///
int main()
{
WSADATA wsaData;
int iResult;
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0)
{
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
struct addrinfo* result = NULL, hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the local address and port to be used by the server
iResult = getaddrinfo("109.xxx.xxx.xxx", "1337", &hints, &result);
if (iResult != 0)
{
printf("getaddrinfo failed: %d\n", iResult);
WSACleanup();
return 1;
}
SOCKET ConnectSocket = INVALID_SOCKET;
for(struct addrinfo* ptr = result; ptr != NULL; ptr = ptr->ai_next)
{
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET)
{
printf("Error at socket(): %d\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
iResult = connect(ConnectSocket, result->ai_addr, (int)result->ai_addrlen);
freeaddrinfo(result);
if (iResult != SOCKET_ERROR)
break;
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
}
if (ConnectSocket == INVALID_SOCKET)
{
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
#define DEFAULT_BUFLEN 512
const char* sendbuf = "this is a test";
char recvbuf[DEFAULT_BUFLEN];
// Send an initial buffer
iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
if (iResult == SOCKET_ERROR)
{
printf("send failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %ld\n", iResult);
// shutdown the connection for sending since no more data will be sent
// the client can still use the ConnectSocket for receiving data
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR)
{
printf("shutdown failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// Receive data until the server closes the connection
do
{
iResult = recv(ConnectSocket, recvbuf, sizeof(recvbuf), 0);
if (iResult > 0)
printf("Bytes received: %d\n", iResult);
else if (iResult == 0)
printf("Connection closed\n");
else
printf("recv failed: %d\n", WSAGetLastError());
}
while (iResult > 0);
shutdown(ConnectSocket, SD_RECEIVE);
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
I have a simple TCP server app that is not accepting any connections.
It is curently built using vs 2019, but was originally built (a while ago) with vs 2012.
The original version works but the 2019 version never accepts.
What areas can I look into?
I do not have access to the client code.
Here is my sever code
int iResult;
WSADATA wsaData;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
#define DEFAULT_PORT "8082"
struct addrinfo* result = NULL, * ptr = NULL, hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the local address and port to be used by the server
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed: %d\n", iResult);
WSACleanup();
return 1;
}
SOCKET ListenSocket = INVALID_SOCKET;
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("Error at socket(): %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
printf("bound\n");
if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR) {
printf("Listen failed with error: %ld\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
SOCKET ClientSocket;
ClientSocket = INVALID_SOCKET;
// Accept a client socket
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
printf("connected\n");
This is the wireshark output
and this is from netsat
Found the issue
It was the firewall stopping the connection requests
This question already has answers here:
TCP Winsock: accept multiple connections/clients
(2 answers)
Closed 6 years ago.
This is the code I have currently, and I'm looking into introducing threads to allow the server process multiple clients at once, however I'm having a little trouble understanding exactly how to do this. Any help would be appreciated.
Client:
int create_client()
{
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
char *sendbuf = "this is a test";
char recvbuf[DEFAULT_BUFLEN];
int iResult;
int recvbuflen = DEFAULT_BUFLEN;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
iResult = getaddrinfo(DEFAULT_IP, DEFAULT_PORT, &hints, &result);
if ( iResult != 0 ) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Attempt to connect to an address until one succeeds
for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Connect to server.
iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
// Send an initial buffer
iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %ld\n", iResult);
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if ( iResult > 0 )
printf("Bytes received: %d\n", iResult);
else if ( iResult == 0 )
printf("Connection closed\n");
else
printf("recv failed with error: %d\n", WSAGetLastError());
} while( iResult > 0 );
// cleanup
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
Server:
WSADATA wsaData;
int iResult;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
int iSendResult;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Create a SOCKET for connecting to server
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
// Setup the TCP listening socket
iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
cout << "Server initalized." << endl;
// Accept a client socket
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
// No longer need server socket
closesocket(ListenSocket);
// Receive until the peer shuts down the connection
do {
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (iResult > 0) {
printf("Bytes received: %d\n", iResult);
// Echo the buffer back to the sender
iSendResult = send(ClientSocket, recvbuf, iResult, 0);
if (iSendResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
printf("Bytes sent: %d\n", iSendResult);
} else if (iResult == 0)
printf("Connection closing...\n");
else {
printf("recv failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
} while (iResult > 0);
// shutdown the connection since we're done
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
// cleanup
closesocket(ClientSocket);
WSACleanup();
return 0;
}
You should separate the listening and the processing parts.
So, your main thread will listen the socket, and when recieve some connection create a threa.
The thread will accept the connection to have the client socket, the read and process.
Pseudocode for you main thread:
while (true){
listen the socket
if any entry connection{
create thread and process the petition
}
}
Pseudocode for you threads:
accept connection and obtain the client socket
process it
close the client socket
EDIT:
PD: This is only a temporal solution, in any real life situation that have huge petitions this won't work well.
I am working on a simple server program and it works perfectly using 127.0.0.1 but when I set the IP to a client (100.2.132.128) who is running the client the server only can receive and am unable to send. The code is mostly based off MSDN. I used Wire shark to capture the traffic between Wire Shark.
The source code for the server attempting to send data to the client:
#pragma once
#pragma comment (lib, "Ws2_32.lib")
#define OUT_DEFAULT_BUFLEN 512
#define OUT_DEFAULT_PORT "20000"
bool Send(std::string arg, std::string IP){
if (arg.size() > 250){
return false;
}
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL, *ptr = NULL, hints;
int iResult;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
iResult = getaddrinfo(IP.c_str(), OUT_DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Attempt to connect to an address until one succeeds
for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Connect to server.
iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
return 1;
}
char *cstr = InAppendSizePacket(arg);
iResult = send(ConnectSocket, cstr, (int)strlen(cstr), 0);
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %ld\n", iResult);
char recvbuf[OUT_DEFAULT_BUFLEN];
int recvbuflen = OUT_DEFAULT_BUFLEN;
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if (iResult > 0){
printf("Bytes received: %d\n", iResult);
if (recvbuf[0] == 'O' && recvbuf[1] == 'K'){
break;
}
}
else if (iResult == 0){
printf("Connection closed\n");
int debug = 0;
}
else{
printf("recv failed with error: %d\n", WSAGetLastError());
int debug = 0;
}
} while (iResult > 0);
std::cout << "The result is:" << recvbuf << std::endl;
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// cleanup
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
The source code for the client waiting to accept data from the server is:
#pragma comment (lib, "Ws2_32.lib")
#define IN_DEFAULT_BUFLEN 512
#define IN_DEFAULT_PORT "20000"
unsigned __stdcall FTPAcceptSession(void *data){
int iSendResult;
char recvbuf[IN_DEFAULT_BUFLEN];
int recvbuflen = IN_DEFAULT_BUFLEN;
int iResult;
SOCKET ClientSocket = (SOCKET)data;
// Receive until the peer shuts down the connection
ClientQuarry NewPacket;
int err = getpeername(ClientSocket, (struct sockaddr *) &NewPacket.addr, &NewPacket.addr_len);
if (err != 0) {
// error, drop the packet.
closesocket(ClientSocket);
return 0;
}
std::vector<std::string> ToDump;
int amount = 0;
do {
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (iResult > 0) {
printf("Bytes received: %d\n", iResult);
std::string temp = PrependSizePacket(recvbuf);
amount++;
ToDump.push_back(temp); //Add to the buffer.
}
else if (iResult == 0)
printf("Connection closing...\n");
else{
printf("recv failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
return 1;
}
char* LK = "OK";
iSendResult = send(ClientSocket, LK, iResult, 0);
if (iSendResult == SOCKET_ERROR || iSendResult == WSAEFAULT) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
return 1;
}
printf("Bytes sent: %d\n", iSendResult);
} while (iResult > 0);
// shutdown the connection since we're done
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
return 1;
}
closesocket(ClientSocket);
return 0;
}
DWORD WINAPI FileTransferProtocol(LPVOID lpParam){
WSADATA wsaData;
int iResult;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = getaddrinfo(NULL, IN_DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Create a SOCKET for connecting to server
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
// Setup the TCP listening socket
iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
for (;;){
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
break;
}
unsigned threadID;
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &FTPAcceptSession, (void*)ClientSocket, 0, &threadID);
}
// shutdown the connection since we're done
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
// cleanup
closesocket(ClientSocket);
WSACleanup();
return 0;
}
I added the program to firewall, open ports 20001 and 20000 for it. The server seems to timeout on the connect() request but I can't figure out why.
I have code (my c++ socket server) but I don't know How can I always open. My server will close. when It already send to client It will close itself. But I want it to wait others client and never closed. How can I do it ? Oh I use multi-threaded too.
please,Help me.
and here is my code
int main(void)
{
HANDLE hThread[3];
DWORD dwID[3];
DWORD dwRetVal = 0;
hThread[0] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadTwo,NULL,0,&dwID[0]);
dwRetVal = WaitForMultipleObjects(3, hThread, TRUE, INFINITE);
CloseHandle(hThread[0]);
return 0;
}
long WINAPI ThreadTwo(long lParam)
{
WSADATA wsaData;
SOCKET ListenSocket = INVALID_SOCKET,
ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
hints;
char recvbuf[DEFAULT_BUFLEN];
int iResult, iSendResult;
int recvbuflen = DEFAULT_BUFLEN;
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if ( iResult != 0 ) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
printf("Waiting for client\n");
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
printf("Client acctped.\n");
closesocket(ListenSocket);
do {
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (iResult > 0) {
printf("Bytes received: %d\n", iResult);
recvbuf[iResult] = '\0';
printf(recvbuf);
char* testsend = "222 333\n444 555\n666 777" ;
iSendResult = send( ClientSocket, testsend , strlen(testsend)+1 , 0 );
if (iSendResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
printf("Bytes sent: %d\n", iSendResult);
}
else if (iResult == 0)
printf("Connection closing...\n");
else {
printf("recv failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
} while (iResult > 0);
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
system("pause");
closesocket(ClientSocket);
WSACleanup();
return 0;
}
thank again.
You have to use a loop for that :)
Basically, the server main code must be in a loop, that will go forever ... while you do not stop it.
you should have :
// That's close to pseudo code :)
while(notStoppedByMaster)
{
// [...]
ClientSocket = accept(ListenSocket, NULL, NULL);
handleRequest(ClientSocket);
}
// close the listen socket here
The handleRequest should handle the request in another thread. Be attentive to synchronization :)
my2c
Firstly, it looks like you are creating a console application. If I were you I would create a WIN32 application instead. This means you'll have a GUI but more importantly, a message loop. The message loop allows you to use Asynchronous sockets, it takes a little more understanding but it gives much better and cleaner results.
Read about WSAAsyncSelect:
http://msdn.microsoft.com/en-us/library/ms741540%28VS.85%29.aspx
Also read socket tutorial:
http://msdn.microsoft.com/en-us/library/ms738545%28v=VS.85%29.aspx
Secondly, if you HAVE to use synchronous (blocking) sockets, yes you'll have to be running each on its own thread. You Need to have a loop in which you wait for connections, and then have client sockets like you did, being assigned from your accept(). Then let the client sockets run on their own thread.
Also you are closing your listensocket for some reason in the middle of the code.