WinSock 2.2: accept() causes virus found - winsock

I made a Windows program with WinAPI and WinSock 2.2. But when I call the accept() function and compile the program, AntiVir tells me that it found a virus ("BDS/Backdoor.Gen") im my application.
This are the important parts of my code:
...
DWORD WINAPI winMsgServerAcceptThread(LPVOID);
SOCKET mSocket;
SOCKET mSocket2;
WSADATA wsaData;
sockaddr_in socketService;
...
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
...
switch(uMsg)
{
case WINMSG_WM_INITSOCKET:
{
int wsaErr = WSAStartup(MAKEWORD(2, 2), &wsaData);
if(wsaErr != 0)
{
swprintf(statusBuffer, 10000, L"%s\r\n\r\nError: WSAStartup() returned code 0x%x!", statusBuffer, WSAGetLastError());
SendMessage(hwnd, WINMSG_WM_UPDATE_STATUS, 0, 0);
WSACleanup();
return 0;
}
if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
swprintf(statusBuffer, 10000, L"%s\r\n\r\nError: System doesn't support WinSock version 2.2!", statusBuffer);
SendMessage(hwnd, WINMSG_WM_UPDATE_STATUS, 0, 0);
WSACleanup();
return 0;
}
mSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(mSocket == INVALID_SOCKET)
{
swprintf(statusBuffer, 10000, L"%s\r\n\r\nError: socket() returned code 0x%x!", statusBuffer, WSAGetLastError());
SendMessage(hwnd, WINMSG_WM_UPDATE_STATUS, 0, 0);
closesocket(mSocket);
WSACleanup();
return 0;
}
//Read own IP
wchar_t ownIPWC[20];
hostent *thisHost = gethostbyname("");
strcpy(ownIP, inet_ntoa(*(struct in_addr*)*thisHost->h_addr_list));
mbstowcs(ownIPWC, ownIP, 20);
swprintf(statusBuffer, 10000, L"%s\r\n\r\nSocket with IP %s successfully initialized!", statusBuffer, ownIPWC);
SendMessage(hwnd, WINMSG_WM_UPDATE_STATUS, 0, 0);
return 0;
}
...
case WINMSG_WM_CREATE_CONNECTION:
{
wchar_t serverIPString[20];
swprintf(statusBuffer, 10000, L"%s\r\n\r\nEstablish connection...", statusBuffer);
SendMessage(hwnd, WINMSG_WM_UPDATE_STATUS, 0, 0);
socketService.sin_family = AF_INET;
socketService.sin_addr.s_addr = inet_addr(WINMSG_RECV_IP);
socketService.sin_port = htons(WINMSG_STD_PORT);
if(connect(mSocket, (SOCKADDR*)&socketService, sizeof(socketService)) == SOCKET_ERROR) //Am I client?
{
closesocket(mSocket);
mSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
socketService.sin_addr.s_addr = inet_addr(ownIP);
mbstowcs(serverIPString, ownIP, 20);
if(bind(mSocket, (SOCKADDR*)&socketService, sizeof(socketService)) == SOCKET_ERROR) //No, I am server
{
swprintf(statusBuffer, 10000, L"%s\r\n\r\nError: bind() returned code 0x%x!", statusBuffer, WSAGetLastError());
SendMessage(hwnd, WINMSG_WM_UPDATE_STATUS, 0, 0);
closesocket(mSocket);
WSACleanup();
return 0;
}
else
{
if(listen(mSocket, 10) == SOCKET_ERROR)
{
swprintf(statusBuffer, 10000, L"%s\r\n\r\nError: listen() returned code 0x%x!", statusBuffer, WSAGetLastError());
SendMessage(hwnd, WINMSG_WM_UPDATE_STATUS, 0, 0);
closesocket(mSocket);
WSACleanup();
return 0;
}
else
{
swprintf(statusBuffer, 10000, L"%s\r\n\r\nlisten() successful! Wait for client...", statusBuffer);
SendMessage(hwnd, WINMSG_WM_UPDATE_STATUS, 0, 0);
CreateThread(NULL, NULL, winMsgServerAcceptThread, 0, 0, &winMsgServerAcceptThreadID);
return 0;
}
}
}
else
{
swprintf(statusBuffer, 10000, L"%s\r\n\r\nConnection with %s:%d established!", statusBuffer, serverIPString, WINMSG_STD_PORT);
connectionAvailable = 1;
SendMessage(hwnd, WINMSG_WM_UPDATE_STATUS, 0, 0);
return 0;
}
return 0;
}
}
}
DWORD WINAPI winMsgServerAcceptThread(LPVOID lpParam)
{
mSocket2 = SOCKET_ERROR;
while(mSocket2 == SOCKET_ERROR)
mSocket2 = accept(mSocket, NULL, NULL);
closesocket(mSocket);
SendMessage(hwnd, WINMSG_WM_CLIENT_ACCEPTED, NULL, NULL);
return 0;
}
If I delete the accept()-function in "winMsgServerAcceptThread", the program can be executed and no virus is detected.
What do I have to change to make my program not longer detected by AntiVir?
EDIT 1:
Here is a shortened and smaller version of the program above:
#ifndef UNICODE
#define UNICODE
#endif
#pragma comment (lib, "wsock32.lib")
#include <stdio.h>
#include <winsock2.h>
int main()
{
SOCKET mSocket;
SOCKET acceptSocket;
WSADATA wsaData;
sockaddr_in socketService;
int wsaErr;
wchar_t serverIP[50];
wsaErr = WSAStartup(MAKEWORD(2, 2), &wsaData);
if(wsaErr == 0)
printf("Winsock DLL found!\n");
mSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(mSocket != INVALID_SOCKET)
printf("socket() successful!\n");
socketService.sin_family = AF_INET;
socketService.sin_addr.s_addr = inet_addr("127.0.0.1");
socketService.sin_port = htons(55555);
if(bind(mSocket, (SOCKADDR*)&socketService, sizeof(socketService)) != SOCKET_ERROR)
printf("bind() with 127.0.0.1:55555 successful!\n");
if(listen(mSocket, 10) != SOCKET_ERROR)
printf("listen() successful!\nWait for client...\n");
while(1)
{
acceptSocket = SOCKET_ERROR;
while(acceptSocket == SOCKET_ERROR)
acceptSocket = accept(mSocket, NULL, NULL);
break;
}
mSocket = acceptSocket;
printf("Connected with client!");
return 0;
}

Related

TCP connection fails at recv() function

I'm a newbie in socket programming.
I'm trying to interface in TCP between server and client by following a certain protocol.
After the connection is established, the communication starts by client sending a certain packet to the server. My program fails at the recv() function at client side.
Let me share you the client side of my code:
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;
iResult = getaddrinfo(LOCAL_IP, "8081", &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;
}
MSG_PDDAU_INFO_PACKET* ps8ptr = new MSG_PDDAU_INFO_PACKET;
memset(ps8bufrecv, 0, DEFAULT_BUFLEN);
s32packetlen = sizeof(MSG_PDDAU_INFO_PACKET);
printf("size %d\n", sizeof(MSG_PDDAU_INFO_PACKET));
iResult = recv(ConnectSocket, ps8bufrecv, s32packetlen, 0);
if (iResult == -1)
{
printf("Here !\n");
fprintf(stderr, "recv Error Occurred %s (%d)\n", strerror(errno), errno);
return -1;
}
memcpy(ps8ptr,ps8bufrecv,sizeof(MSG_PDDAU_INFO_PACKET));
And here is the server side of the code:
nErrorStatus = WSAStartup(wVersionRequested, &wsaData);
serv_sock = socket(PF_INET, SOCK_STREAM, 0);
if(serv_sock == -1)
{
printf( "socket() Error..Error --> Code %d ", WSAGetLastError() );
error_handling("socket error");
}
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = PF_INET;
serv_addr.sin_addr.s_addr = inet_addr(ip);
serv_addr.sin_port = htons(CLIENT_PORT_NUMBER);
if(bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1)
{
printf( "bind() Error..Error --> Code %d ", WSAGetLastError() );
error_handling("bind error");
}
if(listen(serv_sock, 5) == -1)
{
printf( "listen() Error..Error --> Code %d ", WSAGetLastError() );
error_handling("listen error");
}
clnt_addr_size = sizeof(clnt_addr);
clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
if(clnt_sock == -1)
{
printf( "accept() Error..Error --> Code %d ", WSAGetLastError() );
error_handling("accept error");
}
MSG_PDDAU_INFO_PACKET* ps8ptr = new MSG_PDDAU_INFO_PACKET;
ps8ptr->header.msg_id = MSG_PDDAU_INFO_ID;
ps8ptr->header.msg_type = MSG_REQUEST_TYPE;
ps8ptr->time_enable = 0x01;
s32packetlen = sizeof(MSG_PDDAU_INFO_PACKET);
memset(ps8bufsend, 0, DEFAULT_BUFLEN);
memcpy(ps8bufsend,ps8ptr, s32packetlen);
iResult = send(clnt_sock, ps8bufsend, s32packetlen, 0);
if (iResult == -1)
{
fprintf(stderr, "send Error Occurred %s (%d)\n", strerror(errno), errno);
return -1;
}
The code keeps failing at the first recv/send interface after the connection, and the error message looks like below.
Server side:
Time msg id : 5
Time setting failed
Client side:
recv Error Occurred Invalid argument (22)
I don't know what's the correct way to communicate in my case.
It'd be great if anyone can point out my problem here.

Why is the client's file descriptor used while calling the recv and send funtions on both server and client sides?

TCPServer
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/ip.h>
#include<netinet/in.h>
#include<string.h>
#include<stdlib.h>
int main()
{
int fd = socket(AF_INET, SOCK_STREAM, 0);
if(fd == -1)
{
printf("socket failed!\n");
exit(0);
}
printf("Enter port: ");
int port;
scanf("%d",&port);
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = INADDR_ANY;
int bind_ret = bind(fd, (struct sockaddr*)(&server), sizeof(server));
if(bind_ret == -1)
{
printf("bind failed!\n");
exit(0);
}
int listen_ret = listen(fd, 10);
if(listen_ret == -1)
{
printf("listen failed!\n");
exit(0);
}
struct sockaddr_in client;
int l = sizeof(client);
int client_fd = accept(fd, (struct sockaddr*)(&client), &l);
if(client_fd == -1)
{
printf("accept failed!\n");
exit(0);
}
while(1)
{
char msg_recv[50];
int recv_ret = recv(client_fd, msg_recv, sizeof(msg_recv),0);
if(recv_ret == -1)
{
printf("recv failed!\n");
exit(0);
}
msg_recv[recv_ret]='\0';
if(strcmp("bye",msg_recv)==0)
{
exit(0);
}
printf("Message recieved: %s\n",msg_recv);
char msg_send[50];
printf("Enter message: ");
scanf(" %s",msg_send);
int send_ret = send(client_fd, msg_send, strlen(msg_send),0);
if(send_ret == 0)
{
printf("send failed!\n");
}
if(strcmp("bye",msg_send) == 0)
exit(0);
}
}
TCPClient
#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/ip.h>
#include<netinet/in.h>
#include<string.h>
#include<stdlib.h>
int main()
{ int fd = socket(AF_INET, SOCK_STREAM, 0);
if(fd == -1)
{
printf("socket failed!\n");
exit(0);
}
int port;
printf("Enter port number: ");
scanf("%d",&port);
struct sockaddr_in client;
client.sin_family = AF_INET;
client.sin_port = htons(port);
client.sin_addr.s_addr = INADDR_ANY;
int connect_ret = connect(fd, (struct sockaddr*)(&client), sizeof(client));
if(connect_ret == -1)
{
printf("connect failed!\n");
exit(0);
}
while(1)
{
printf("Enter message: ");
char msg_send[50];
scanf("%s",msg_send);
int send_ret = send(fd, msg_send, strlen(msg_send), 0);
if(send_ret == -1)
{
printf("send failed!\n");
exit(0);
}
if(strcmp("bye", msg_send)==0)
{
exit(0);
}
char msg_recv[50];
int recv_ret = recv(fd, msg_recv, sizeof(msg_recv), 0);
if(recv_ret == -1)
{
printf("recv failed!\n");
exit(0);
}
msg_recv[recv_ret]= '\0';
if(strcmp("bye", msg_recv) == 0)
exit(0);
printf("Message recieved: %s \n",msg_recv);
}
}
In the above program for Server, recv and send were called by passing client_fd as the argument, while in the program for Client, recv and send were called by passing fd as the argument. I wanted to know why on the server side we did not use its own socket file descriptor like we did on the client side?
The server’s fd descriptor is a listen()’ing socket. It can’t perform any I/O, only receive incoming client connections. accept() pulls a pending client connection from fd’s queue and returns a new socket descriptor that can perform I/O with that client.
The client’s fd descriptor is a connect()‘ing socket. It can perform I/O with the server once its connection has been accepted.

send failed with error 10093 and shutdown failed with error 10093

class socketClient
{
private:
SOCKET ConnectSocket;
int numBlock;
public:
socketClient()
{
WSADATA wsaData;
numBlock = countObj;
++countObj;
int iResult;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0)
{
ssPrintf("WSAStartup failed: %d\n", iResult);
//return 1;
}
// Create a SOCKET for connecting to server
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET)
{
ssPrintf("Error at socket(): %ld\n", WSAGetLastError());
//freeaddrinfo(result);
WSACleanup();
//return 1;
}
}
void sConnect(char* myHost, int myPort)
{
int iResult;
char port[5];
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;
_itoa_s(myPort,port,5,10);
iResult = getaddrinfo(myHost, porgt, &hints, &result);
if ( iResult != 0 )
{
ssPrintf("getaddrinfo failed: %d\n", iResult);
WSACleanup();
//return 1;
}
// Connect to server.
iResult = connect( ConnectSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR)
{
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
}
}
~socketClient()
{
int iResult;
--countObj;
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR)
{
printf("shutdown failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
//return 1;
}
closesocket(ConnectSocket);
WSACleanup();
}
int getNumBlock()
{
return numBlock;
}
int sWrite(std::string str)
{
int iResult;
// Send an string
iResult = send( ConnectSocket, str.c_str(), str.size(), 256 );
if (iResult == SOCKET_ERROR)
{
ssPrintf("send failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
//return 1;
}
return iResult; //pocet odeslanych bytu
}
};
I am trying to send string to the client model but while running the model, I am getting error as:
send failed 10093 and
shutdown failed 10093.
Please do let me know what can I change in this code.
Socket error 10093 (WSANOTINITIALIZED) means either:
WSAStartup() has not been called, or it failed
WSACleanup() has been called too many times.
In this case, your code is calling WSACleanup() in places it does not belong:
sConnect() calls WSACleanup() if getaddrinfo() fails
sWrite() calls WSACleanup() if send() fails.
~socketClient() calls WSACleanup() an extra time if shutdown() fails.
WSAStartup() and WSACleanup() must be balanced. For each successful call to WSAStartup(), you must call WSACleanup() once and only once. In this case, only your destructor should be calling WSACleanup(), and only if WSAStartup() was successful in the constructor.
Your code also has other errors in it as well.
Try something more like this instead:
class socketClient
{
private:
SOCKET ConnectSocket;
int numBlock;
bool WSAInitialized;
// private to prevent copies
socketClient(const socketClient&)
: ConnectSocket(INVALID_SOCKET), WSAInitialized(false)
{
numBlock = countObj++;
}
socketClient& operator=(const socketClient&)
{
return *this;
}
public:
socketClient()
: ConnectSocket(INVALID_SOCKET), WSAInitialized(false)
{
numBlock = countObj++;
// Initialize Winsock
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0)
{
ssPrintf("WSAStartup() failed: %d\n", iResult);
return;
}
WSAInitialized = true;
// Create a SOCKET for connecting to server
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET)
{
ssPrintf("socket() failed: %d\n", WSAGetLastError());
return;
}
}
~socketClient()
{
--countObj;
if (ConnectSocket != INVALID_SOCKET)
{
shutdown(ConnectSocket, SD_SEND);
closesocket(ConnectSocket);
}
if (WSAInitialized)
WSACleanup();
}
bool sConnect(char* myHost, int myPort)
{
char port[6];
struct addrinfo *result = NULL,
hints;
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
_itoa_s(myPort, port, 6, 10);
int iResult = getaddrinfo(myHost, port, &hints, &result);
if (iResult != 0)
{
ssPrintf("getaddrinfo() failed: %d\n", iResult);
return false;
}
// Connect to server.
if (connect(ConnectSocket, result->ai_addr, (int)result->ai_addrlen) == SOCKET_ERROR)
{
ssPrintf("connect() failed: %d\n", WSAGetLastError());
freeaddrinfo(result);
return false;
}
freeaddrinfo(result);
return true;
}
int getNumBlock()
{
return numBlock;
}
bool sWrite(const std::string &str)
{
int iResult;
const char *ptr = str.c_str();
int len = str.size();
// Send an string
while (len > 0)
{
iResult = send( ConnectSocket, ptr, len, 0 );
if (iResult == SOCKET_ERROR)
{
ssPrintf("send() failed: %d\n", WSAGetLastError());
return false;
}
ptr += iResult;
len -= iResult;
}
return true;
}
};
Since you are coding in C++, you should consider using exceptions and RAII techniques instead, eg:
#include <stdexcept>
#include <memory>
class winsock_error : public std::runtime_error
{
public:
int errorCode;
winsock_error(const std::string &msg, int error)
: std::runtime_error(msg), errorCode(error)
{
}
};
class wsaInit
{
private:
void init()
{
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0)
throw winsock_error("WSAStartup() failed", iResult);
}
public:
wsaInit()
{
init();
}
wsaInit(const wsaInit &)
{
init();
}
~wsaInit()
{
WSACleanup();
}
};
struct socketDeleter
{
typedef SOCKET pointer;
void operator()(SOCKET s)
{
if (s != INVALID_SOCKET)
{
shutdown(s, SD_BOTH);
closesocket(s);
}
}
};
typedef std::unique_ptr<SOCKET, socketDeleter> socket_ptr;
typedef std::unique_ptr<struct addrinfo, decltype(&freeaddrinfo)> addrinfo_ptr;
class socketClient
{
private:
wsaInit wsa;
socket_ptr ConnectSocket;
int numBlock;
public:
socketClient()
: ConnectSocket(INVALID_SOCKET)
{
numBlock = countObj++;
}
socketClient(const socketClient&) = delete;
socketClient& operator=(const socketClient&) = delete;
~socketClient()
{
--countObj;
}
void sConnect(char* myHost, int myPort)
{
char port[6];
struct addrinfo *result = NULL,
hints;
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
_itoa_s(myPort, port, 6, 10);
int iResult = getaddrinfo(myHost, port, &hints, &result);
if (iResult != 0)
throw winsock_error("getaddrinfo() failed", iResult);
addrinfo_ptr result_ptr(result, &::freeaddrinfo);
// Connect to server.
int errorCode = 0;
for(struct addrinfo *ptr = result; ptr != NULL; ptr = ptr->ai_next)
{
// Create a SOCKET for connecting to server
socket_ptr sock( socket(result->ai_family, result->ai_socktype, result->ai_protocol) );
if (sock.get() == INVALID_SOCKET)
throw winsock_error("socket() failed", WSAGetLastError());
if (connect(sock.get(), result->ai_addr, (int)result->ai_addrlen) != SOCKET_ERROR)
{
ConnectSocket = std::move(sock);
return;
}
errorCode = WSAGetLastError();
}
throw winsock_error("connect() failed", errorCode);
}
int getNumBlock()
{
return numBlock;
}
void sWrite(const std::string &str)
{
int iResult;
const char *ptr = str.c_str();
int len = str.size();
// Send an string
while (len > 0)
{
iResult = send(ConnectSocket.get(), ptr, len, 0);
if (iResult == SOCKET_ERROR)
throw winsock_error("send() failed", WSAGetLastError());
ptr += iResult;
len -= iResult;
}
}
};

Winsock non-blocking overlapped IO still blocks

I am trying to write a simple winsock client that sends data to a
winsock server using non-blocking overlapped IO. The problem is that the WSASend call is blocking. The client code looks like this
// Initialize Winsock
WSAStartup(MAKEWORD(2, 2), &wsaData);
// Create a SOCKET for connecting to server
ConnectSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
// Connect to server.
WSAConnect(ConnectSocket, ai_addr, ai_addrlen, 0, 0, 0, 0);
// Make the socket non-blocking
u_long iMode = 1;
ioctlsocket(ConnectSocket, FIONBIO, &iMode);
// Send the data
WSAOVERLAPPED SendOverlapped{};
SendOverlapped.hEvent = WSACreateEvent();
WSASend(ConnectSocket, &DataBuf, 1, &SendBytes, 0, &SendOverlapped, 0);
I have made the socket non-blocking through the ioctlsocket function and I have provided WSA_FLAG_OVERLAPPED flag to the WSASocket function. I have also provided the lpOverlapped parameter to the WSASend function. However, the call to WSASend is still blocking. Am I missing something here?
Please excuse the lack of error checking in the above code, it is only to keep it simple for the purposes of this question.
Clarification: The reason why it seems to me the call is blocking is this - I called the WSASend function 2560 times in a loop, sending 4MB each time in the loop. The loop completed in 16 secs after all the data was transferred to the server. If it was non-blocking, I would have expected the loop to complete much sooner. As expected, the WSASend function does return with ERROR_IO_PENDING though.
Here is the full client code
// Client.cpp
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <stdio.h>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream>
#include <ctime>
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
#define DEFAULT_BUFLEN 4 * 1024 * 1024
#define DEFAULT_PORT "27015"
int __cdecl main(int argc, char **argv)
{
// Initialize Winsock
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
// Resolve the server address and port
addrinfo *result = NULL;
addrinfo hints{};
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
iResult = getaddrinfo("127.0.0.1", 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
SOCKET ConnectSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Connect to server.
iResult = WSAConnect(ConnectSocket, result->ai_addr, result->ai_addrlen, 0, 0, 0, 0);
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
// Make the socket non-blocking
u_long iMode = 1;
iResult = ioctlsocket(ConnectSocket, FIONBIO, &iMode);
if (iResult != NO_ERROR) {
printf("ioctlsocket failed with error: %ld\n", iResult);
WSACleanup();
return 1;
}
// Prepare the buffer
char *sendbuf = new char[DEFAULT_BUFLEN];
for (int i = 0; i < DEFAULT_BUFLEN; ++i)
sendbuf[i] = 'a';
WSABUF DataBuf;
DWORD SendBytes = 0;
DataBuf.buf = sendbuf;
DataBuf.len = DEFAULT_BUFLEN;
// Send the buffer in a loop
int loopCount = 2560;
WSAOVERLAPPED* SendOverlapped = (WSAOVERLAPPED*)calloc(loopCount, sizeof(WSAOVERLAPPED));
clock_t start = clock();
for (int i = 0; i < loopCount; ++i)
{
SendOverlapped[i].hEvent = WSACreateEvent();
iResult = WSASend(ConnectSocket, &DataBuf, 1, &SendBytes, 0, SendOverlapped + i, 0);
if (iResult == SOCKET_ERROR)
{
if (ERROR_IO_PENDING == WSAGetLastError())
{
continue;
}
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
}
std::cout << "initiating send data took " << clock() - start << " ms" << std::endl;
// Wait for all the events to be signalled
for (int i = 0; i < loopCount; ++i)
{
iResult = WSAWaitForMultipleEvents(1, &SendOverlapped[i].hEvent, TRUE, INFINITE, TRUE);
if (iResult == WSA_WAIT_FAILED) {
printf("WSAWaitForMultipleEvents failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
DWORD Flags = 0;
BOOL result = WSAGetOverlappedResult(ConnectSocket, SendOverlapped + i, &SendBytes, FALSE, &Flags);
if (result == FALSE) {
printf("WSASend failed with error: %d\n", WSAGetLastError());
break;
}
}
std::cout << "actual send data took " << clock() - start << " ms";
// 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;
}
// cleanup
closesocket(ConnectSocket);
WSACleanup();
////free(SendOverlapped);
return 0;
}
And here is the server side code
// Server.cpp
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <stdio.h>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream>
#pragma comment (lib, "Ws2_32.lib")
#define DEFAULT_BUFLEN 4 * 1024 * 1024
#define DEFAULT_PORT "27015"
int __cdecl main(void)
{
// Initialize Winsock
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
// Resolve the server address and port
addrinfo hints{};
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
addrinfo *result = NULL;
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
SOCKET 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;
}
// Accept a client socket
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
char* recvbuf = new char[DEFAULT_BUFLEN];
do {
iResult = recv(ClientSocket, recvbuf, DEFAULT_BUFLEN, 0);
if (iResult > 0) {
printf("Bytes received: %d\n", iResult);
}
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;
}
The WSASend call was blocking because it was completing too quickly. One would think a 4MB transfer would be sufficiently large to call for async processing but that was not the case. When I inserted a sleep of 1 ms on the server side, I could see the client processing asynchronously, and the loop ended much before the data transfer.

Issue with retrieving client IP address on a winsock 2 based server program

Hello I made this program based on the msdn winsock2.h tutorial.I have server program and a client one.Everything works fine, I even made one sided chat from the server to the client, more like broadcast.Now i want to see the client's IP address when he connects.I think i did it right but, on every connect it shows different address in strange form like 12.2.90.0 then, 12.2.46.0.
This is the server code :
#include <cstdlib>
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <iphlpapi.h>
#define DEFAULT_PORT "27015"
using namespace std;
int main(int argc, char *argv[])
{
WSADATA wsaData;
int iResult;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct sockaddr_in client_info;
char * addr;
struct addrinfo *result = NULL;
struct addrinfo hints;
int iSendResult;
char buffer[50];
char typebuffer[50];
char connected_ip[15]= "\0";
int port;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
} cout<<"Winsock initialized..."<<endl;
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;
} else cout<<"Listening socket initialized...\nAccepting connections now..."<<endl;
freeaddrinfo(result);
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
// Accept a client socket
ClientSocket = accept(ListenSocket, (struct sockaddr*)&client_info, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
} else
// converting the address in readable form
addr = inet_ntoa(client_info.sin_addr);
printf("Client connected, IP address is: %s\n", addr );
{
}
closesocket(ListenSocket);
for(;;)
{
cin.getline(typebuffer,50);
strcpy(buffer,"SERVER: ");
strcat(buffer,typebuffer);
send( ClientSocket, buffer, 50, 0 );
*buffer = '\0';
}
system("PAUSE");
return EXIT_SUCCESS;
}
You are providing a sockaddr_in struct to accept(), but you are not telling it how large the struct is. You are not zeroing out the sockaddr_in, and accept() is not filling it in, so you end up with random results when calling inet_ntoa(). This behavior is documented:
accept function
If addr and/or addrlen are equal to NULL, then no information about the remote address of the accepted socket is returned.
The addrlen parameter cannot be NULL if the addr parameter is not NULL:
int addrlen = sizeof(client_info); // <-- Add this
ClientSocket = accept(ListenSocket, (struct sockaddr*)&client_info, &addrlen);