Asynchronous data reading from server using WinSock - c++

I am using the WinSock API in C++ to connect and send data to a specific server (to increase readability, all the code is without error handling):
#include <winsock2.h>
#include <Windows.h>
#define PORT 5051
WSADATA WsaData;
WSAStartup(MAKEWORD(2, 2), &WsaData);
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SOCKADDR_IN sin;
ZeroMemory(&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr("Some valid IP");
connect(s, (sockaddr *) &sin, sizeof(sin));
string sdata_out = "Something like GET request\n";
send(s, sdata_out.c_str(), sdata_out.size(), 0);
The server will start to sending responses, separated by different periods of time. It will send responses without additional requests from me.
I need to read this data asynchronously (not cycle of recv() functions).
I tried to use WSAEventSelect() to listen on the local socket, like this:
SOCKET sloc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SOCKADDR_IN sinloc;
ZeroMemory(&sinloc, sizeof(sinloc));
sinloc.sin_family = AF_INET;
sinloc.sin_port = htons(PORT);
sinloc.sin_addr.s_addr = INADDR_ANY;
WSAEventSelect(sloc, EventArray[EventTotal - 1], FD_ACCEPT |
FD_CLOSE | FD_READ | FD_CONNECT) == SOCKET_ERROR)
bind(sloc, (sockaddr *)&sinloc, sizeof(sinloc));
listen(sloc, 5));
I have no idea what to do further. I tried following this example, but my program got stuck at runtime on this code:
DWORD Event = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE)
What is the problem? How should my event handler function look? Or, am I am doing something fundamentally wrong? Is there a correct way to asynchronously read data from the server, if I don't know when the data comes?

Related

How to detect if a port is already in use server side (in C++ on windows)?

It's certainly a common question, but not in this terms (windows, server side, accept multi connexion).
My goal is to accept to start a server listing on a port for multiple connections only if before that the port is detected "unused".
At the line where I put //HERE..., binddoesn't return a SOCKET_ERROR status as I expected.
Maybe I'm doing something wrong.
How to detect that my port is not in use by some other app?
Here is the status of the port before running (it is used)
netstat -an
TCP 127.0.0.1:2005 0.0.0.0:0 LISTENING
I hope this snippet is sufficent to explain what I'm doing, it's a merge of several steps.
WSADATA WSAData;
int err = WSAStartup(MAKEWORD(2, 2), &WSAData);
SOCKADDR_IN sin;
socklen_t recsize = sizeof(sin);
int one = 1;
SOCKADDR_IN* csin;
SOCKET csock = INVALID_SOCKET;
socklen_t crecsize = sizeof(SOCKADDR_IN);
int sock_err;
if (m_socket != INVALID_SOCKET)
{
memset(&sin, 0, recsize);
if(m_blocal)
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
else
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_family = AF_INET;
sin.sin_port = htons(m_iPort);
setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&one, sizeof(int));
sock_err = bind(m_socket, (SOCKADDR*)&sin, recsize);
//HERE I want to be sure no one else runs on this port
//rest of the code using: select(m_socket + 1, &rd, &wr, &er, &timeout);
}
closesocket(m_socket);
WSACleanup();
Don't set SO_REUSEADDR. Then bind() will fail if the address is already in use and WSAGetLastError() will return WSAEADDRINUSE.
Also note that two processen can still bind to the same port if the IP addresses are different, for example, one process binding to localhost and another process binding to the LAN network address.

SOCKET communication through C++ on Win7 with other than English OS languages

I have a project where I communicate with the server through socket and is running for long period.(Source code below...) However on win 7 with languages as Danish/Chinese on some machines it gives me erorrs like: a particular servelet doesn't exist. Although the connection is created and message is sent but I receive back the message as an error.
Now I want to include winsock2.h with Ws2_32.lib and want to change MAKEWORD(1,1) to MAKEWORD(2,2). How far it is safe for me to go with this change with a project which is running since a long period?
// I have included the basic sources here.
#include <winsock.h>
// with winsock32.lb
SOCKET sockRef = NULL;
struct sockaddr_in srvInfo;
struct hostent *netHostForName = NULL;
WORD wVersionRequested = MAKEWORD(1,1);
int nRet = WSAStartup(wVersionRequested, &wsaData);
netHostForName = gethostbyname(serverName);
memcpy((char *)&srvInfo.sin_addr, netHostForName->h_addr,
netHostForName->h_length);
srvInfo.sin_port = htons(portNumber);
srvInfo.sin_family = AF_INET;
sockRef = socket(AF_INET, SOCK_STREAM, 0);
connect(sockRef, (struct sockaddr *)&srvInfo,sizeof(srvInfo));
// Sending messages with
SockWrite(Socket, message, strlen(message), 0);
//Receiving messages with
recv(Socket, szBuffer, sizeof(szBuffer), 0);
CLOSESOCKET(Socket);
WSACleanup();
its not the socket , its the data , use utf-8 encoded data as char stream.

Read from socket freeze

I have problem while reading data from client on server. The read() function will always freeze (block) after all data are readed and waiting for more data what is undesirable for me.
Server program:
soc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = INADDR_ANY;
bind(soc, (struct sockaddr*) &sin, sizeof(sin));
if (listen(soc, MAX))
return;
int socc; // socket for clinet
while (1) {
if ((socc = accept(soc, (struct sockaddr *) &sin, sinlen)) < 0)
break;
while ((result = read(socc, pointer, SIZE)) > 0) {
// after the data are readed, read function will block
}
// do some stuff and write reply to client => will never done
}
Client program:
...
soc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
struct sockaddr_in socketAddr;
socketAddr.sin_family = AF_INET;
socketAddr.sin_port = htons(port);
memcpy(&(socketAddr.sin_addr), host->h_addr, host->h_length);
if (connect(soc, (sockaddr *)&socketAddr, sizeof(socketAddr)) == -1)
return;
if (write(soc, req.c_str(), strlen(req.c_str())) < 0)
return;
The main problem is that I don't know how much data will be client sending to server, so the server should read all data from socket and after nothing is coming, leave the reading cycle. But the server read whole message for example (30 bytes) and waiting for more (but no more is coming). The sockets are still opened because the client is waiting for reply from server.
You will need to make your socket non-blocking. The read will immediately exit in that case if there is nothing to be read with a specific error.
Look at C- Unix Sockets - Non-blocking read
As stated earlier use non blocking or add RCV_TIMEOUT to socket.
struct timeval tv;
tv.tv_sec = 30; /* 30 Secs Timeout */
setsockopt(sockid, SOL_SOCKET, SO_RCVTIMEO,(struct timeval *)&tv,sizeof(struct timeval));

Receiving multiple messages Winsock2 C++

I am trying to make a program using Winsock2 where I can send a message from client to server. I can do this, but the problem is I can only send one message and then I have to restart the server to receive the next message. Here is the code for the server. The part I am really confused about is I have the recv() function in a while loop so why isn't it continuing to "receive" data?
WSADATA wsaData;
int bytes_recieved;
char data_recieve[2048];
string output;
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SOCKADDR_IN ServerInfo;
ServerInfo.sin_family = AF_INET;
ServerInfo.sin_addr.s_addr = INADDR_ANY;
ServerInfo.sin_port = htons(8888);
bind(ListenSocket, (LPSOCKADDR)&ServerInfo, sizeof(struct sockaddr));
listen(ListenSocket, 1);
SOCKET ClientSocket = accept (ListenSocket, NULL, NULL);
while(true)
{
bytes_recieved = recv(ClientSocket, data_recieve, 2048, 0);
if (bytes_recieved > 1)
{
cout << data_recieve;
}
}
closesocket(ClientSocket);
closesocket(ListenSocket);
WSACleanup();
The client (sender) is listed below.
WSADATA wsaData;
int bytes_sent;
char send_msg[] = "super cool message!";
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in ConnectInfo;
ConnectInfo.sin_family = AF_INET;
ConnectInfo.sin_addr.s_addr = inet_addr("127.0.0.1");
ConnectInfo.sin_port = htons(8888);
connect(ConnectSocket, (SOCKADDR*)&ConnectInfo, sizeof(ConnectInfo));
bytes_sent = send(ConnectSocket, send_msg, sizeof(send_msg), 0);
closesocket(ConnectSocket);
WSACleanup();
I am doing this in Windows 7 with a MinGW compiler. Thank you in advance.
You did not show your client sending code, but offhand, your server reading code is not taking into account that sends and receives are NOT 1-to-1 in TCP/IP programming. If a client sends 2 messages, the server may receive both messages, or even portions of them, in the same read operation! You ae telling your server socket to read 2048 bytes at a time. It will return whatever is currently available on the socket at that moment. TCP/IP is a byte stream, you need to treat it as much. That means you need to either put a delimiter in between your messages, or put a frame around them, in order to know where one message ends and the next message begins.

Socket program Python vs C++ (Winsock)

I have python program which works perfectly for internet chatting. But program built on similar sockets in C++ do not work over internet.
Python program
import thread
import socket
class p2p:
def __init__(self):
socket.setdefaulttimeout(50)
self.port = 3000
#Destination IP HERE
self.peerId = '59.95.18.156'
#declaring sender socket
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM )
self.socket.bind(('', self.port))
self.socket.settimeout(50)
#starting thread for reception
thread.start_new_thread(self.receiveData, ())
while 1:
data=raw_input('>')
#print 'sending...'+data
self.sendData(data)
def receiveData(self):
while 1:
data,address=self.socket.recvfrom(1024)
print data
def sendData(self,data):
self.socket.sendto(data, (self.peerId,self.port))
if __name__=='__main__':
print 'Started......'
p2p()
I want to built similar functionality in c++. I took server and client programs from MSDN. But they are working only on localhost not over internet ..
they are as follows...
Sender
#include <stdio.h>
#include "winsock2.h"
void main() {
WSADATA wsaData;
SOCKET SendSocket;
sockaddr_in RecvAddr;
int Port = 3000;
char SendBuf[3]={'a','2','\0'};
int BufLen = 3;
//---------------------------------------------
// Initialize Winsock
WSAStartup(MAKEWORD(2,2), &wsaData);
//---------------------------------------------
// Create a socket for sending data
SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
//---------------------------------------------
// Set up the RecvAddr structure with the IP address of
// the receiver (in this example case "123.456.789.1")
// and the specified port number.
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = inet_addr("59.95.18.156");
//---------------------------------------------
// Send a datagram to the receiver
printf("Sending a datagram to the receiver...\n");
sendto(SendSocket,
SendBuf,
BufLen,
0,
(SOCKADDR *) &RecvAddr,
sizeof(RecvAddr));
//---------------------------------------------
// When the application is finished sending, close the socket.
printf("Finished sending. Closing socket.\n");
closesocket(SendSocket);
//---------------------------------------------
// Clean up and quit.
printf("Exiting.\n");
WSACleanup();
return;
}
Receiver
#include <stdio.h>
#include "winsock2.h"
#include<iostream>
using namespace std;
void main() {
WSADATA wsaData;
SOCKET RecvSocket;
sockaddr_in RecvAddr;
int Port = 3000;
char RecvBuf[3];
int BufLen = 3;
sockaddr_in SenderAddr;
int SenderAddrSize = sizeof(SenderAddr);
//-----------------------------------------------
// Initialize Winsock
WSAStartup(MAKEWORD(2,2), &wsaData);
//-----------------------------------------------
// Create a receiver socket to receive datagrams
RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
//-----------------------------------------------
// Bind the socket to any address and the specified port.
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(RecvSocket, (SOCKADDR *) &RecvAddr, sizeof(RecvAddr));
//-----------------------------------------------
// Call the recvfrom function to receive datagrams
// on the bound socket.
printf("Receiving datagrams...\n");
while(true){
recvfrom(RecvSocket,
RecvBuf,
BufLen,
0,
(SOCKADDR *)&SenderAddr,
&SenderAddrSize);
cout<<RecvBuf;
}
//-----------------------------------------------
// Close the socket when finished receiving datagrams
printf("Finished receiving. Closing socket.\n");
closesocket(RecvSocket);
//-----------------------------------------------
// Clean up and exit.
printf("Exiting.\n");
WSACleanup();
return;
}
Thank you very much for any help ..
Sorry for too much code in the question.
Per the docs, sendto returns a number that's >0 (number of bytes sent) for success, <0 for failure, and in the latter case you use WSAGetLastError for more information. So try saving the sendto result, printing it (as well as the size of the data you're trying to send), and in case of error print the last-error code too. What do you see then?