I am trying to implement a unit test to see if using the function "WaitForMultipleObjects" works properly with socket. To do so I implemented a simple UDP server-client protocol. The server bind his socket and wait to receive data from receiver using the function "WaitForMultipleObjects". Once the server receives data from the client, it displays it then waits 5 seconds. The problem here that if the client try to send 2 messages during this five seconds, the first one is displayed while the second one will block the function "WaitForMultipleObjects" forever. I know that I can use the "Select" function to do that since the socket is the only object I am waiting for, but it's just a unit test. In my real project I need to wait on a socket and another object's type which is a windows event (which is of type HANDLE) at the same time. And that's why i am trying to use "WaitForMultipleObjects" on sockets.
Here's the server code:
/*
Simple UDP Server
*/
#include<winsock2.h>
#include<windows.h>
#include <ws2tcpip.h>
#include<stdio.h>
#include<iostream>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
#define BUFLEN 512 //Max length of buffer
#define PORT 8888 //The port on which to listen for incoming data
int main()
{
SOCKET s;
struct sockaddr_in server, si_other;
int slen , recv_len;
char buf[BUFLEN];
WSADATA wsa;
HANDLE SEvent;
slen = sizeof(si_other) ;
//Initialise winsock
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Initialised.\n");
//Create a socket
if((s = socket(AF_INET , SOCK_DGRAM , 0 )) == INVALID_SOCKET)
{
printf("Could not create socket : %d" , WSAGetLastError());
}
printf("Socket created.\n");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( PORT );
//Bind
if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
puts("Bind done");
SEvent = WSACreateEvent();
WSAEventSelect( s, SEvent, FD_READ);
//keep listening for data
while(1)
{
printf("Waiting for data...");
fflush(stdout);
//clear the buffer by filling null, it might have previously received data
memset(buf,'\0', BUFLEN);
INT r = WaitForMultipleObjectsEx(1,&SEvent,FALSE,INFINITE,TRUE);
if( r == WAIT_OBJECT_0)
{
if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == SOCKET_ERROR)
{
printf("recvfrom() failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
//print details of the client/peer and the data received
printf("Received packet from %s:%d\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port));
printf("Data: %s\n" , buf);
//now reply the client with the same data
if (sendto(s, buf, recv_len, 0, (struct sockaddr*) &si_other, slen) == SOCKET_ERROR)
{
printf("sendto() failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
ResetEvent(SEvent);
Sleep(5000);
}
else
{
std::cerr<<"WaitForMultipleObject() Error ( "<<GetLastError()<<" )"<<std::endl;
exit(0);
}
}
closesocket(s);
WSACleanup();
return 0;
}
Here's the client code:
/*
Simple udp client
*/
#include<stdio.h>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
#define SERVER "127.0.0.1" //ip address of udp server
#define BUFLEN 512 //Max length of buffer
#define PORT 8888 //The port on which to listen for incoming data
int main(void)
{
struct sockaddr_in si_other;
int s, slen=sizeof(si_other);
char buf[BUFLEN];
char message[BUFLEN];
WSADATA wsa;
//Initialise winsock
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Initialised.\n");
//create socket
if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR)
{
printf("socket() failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
//setup address structure
memset((char *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(PORT);
si_other.sin_addr.S_un.S_addr = inet_addr(SERVER);
//start communication
while(1)
{
printf("Enter message : ");
gets(message);
//send the message
if (sendto(s, message, strlen(message) , 0 , (struct sockaddr *) &si_other, slen) == SOCKET_ERROR)
{
printf("sendto() failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
//receive a reply and print it
//clear the buffer by filling null, it might have previously received data
/*memset(buf,'\0', BUFLEN);
//try to receive some data, this is a blocking call
if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == SOCKET_ERROR)
{
printf("recvfrom() failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
puts(buf);*/
}
closesocket(s);
WSACleanup();
return 0;
}
Note: I didn't write all the code. I used a code that was already written (from the internet) but made some changes.
Does anyone know how to fix this problem? (using "WaitForMultipleObjects" on socket properly)
The problem here that if the client try to send 2 messages during this five seconds, the first one is displayed while the second one will clock the function "WaitForMultipleObjects" forever.
Your server code has a race condition.
Your should call WSAResetEvent/ResetEvent before calling recvfrom, not afterwards. Otherwise, there is a possiblity that new data will arrive between the call to recvfrom and WSAResetEvent, setting the event object to signalled. In that case, WSAResetEvent will set the event back to non-signalled, causing you to lose the notification of new data being available.
Also, according to the documentation of WSAEventSelect, after reading data from a socket, if more data is available to be read, the event will automatically be set to signalled again, in order to indicate that more data is available. If you call WSAResetEvent afterwards, then you will set the event back to non-signalled, causing you to lose the notification of new data being available. This is probably the reason for the behavior you describe in the question.
You should rather call WSAResetEvent/ResetEvent immediately after WSAWaitForMultipleEvents/WaitForMultipleObjectsEx. See the documentation for the function WSAWaitForMultipleEvents for a code example (that example uses overlapped I/O instead of WSAEventSelect, though).
Related
I am trying to send UDP frames from my laptop to another PC as a client-server application using C++. I am monitoring the ethernet port using WireShark and I do not see any information being sent from my laptop. Can someone help regarding this? Am I missing an important step?
/*
Simple udp client
*/
#include "stdafx.h"
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<stdio.h>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
#define SERVER "10.222.14.229"
#define BUFLEN 512
#define PORT 8888
int main(void)
{
struct sockaddr_in si_other;
int s, slen = sizeof(si_other);
char buf[BUFLEN];
char message[BUFLEN];
char message1[] = "Hello";
WSADATA wsa;
//Initialise winsock
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Initialised.\n");
//create socket
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR)
{
printf("socket() failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
memset((char *)&si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(PORT);
si_other.sin_addr.S_un.S_addr = inet_addr(SERVER);
while (1)
{
if (sendto(s, message1, strlen(message1), 0, (struct sockaddr *) &si_other, slen) == SOCKET_ERROR)
{
printf("sendto() failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
memset(buf, '\0', BUFLEN);
puts(buf);
}
closesocket(s);
WSACleanup();
return 0;
}
There's nothing wrong with that code - it runs fine here (apart from the busy loop). Either:
the packets aren't going out on the wire, perhaps because there is no route to 10.222.14.229 (try pinging it), or
WireShark isn't functioning properly (can it see other traffic from your laptop? - it might have a filter set or something)
If you suspect WireShark, you could always try Microsoft Network Monitor.
The solution to this thread:
WireShark was missing the Pincap library when it was installed on Windows 10.
Installing the Pincap library solved the problem.
Edit: Working on a solution - turns out googling 204.204.204.204 gets me further than more descriptive requests.
Honestly. Wits end. I have no idea how I can spend an entire day doing something that took 10 minutes in Flask (Server) and Javascript (client). I need this to run in C++ and allow a client to connect via BlueStacks' port on the same machine. The client is unimportant because I can't even get that far.
I've tried WinSocks, I've tried WxWidget's networking implementation, I've even tried some random C++ wrapper thing. All of them failed (typically within the EXAMPLE! As in, copy paste and errors everywhere). So I ultimately went back to WinSockets and followed a tutorial on YouTube.
int ServerStuff() {
WSADATA WsData;
WORD ver = MAKEWORD(2, 2);
int wsOK = WSAStartup(ver, &WsData);
if (wsOK != 0) {
wxLogMessage("Can't initialize Winsock! Quitting");
return false;
}
//Create a socket
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET) {
wxLogMessage("Can't create a socket! Quitting");
return false;
}
//Bind the ip and port to a socket
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(54000);
hint.sin_addr.S_un.S_addr = INADDR_ANY; //Could also use inet_pton
bind(listening, (sockaddr*)&hint, sizeof(hint));
//Tell winsock the socket is for listening
listen(listening, SOMAXCONN);
//Wait for a connection
sockaddr_in client;
int clientSize = sizeof(client);
SOCKET clientSocket = accept(listening, (sockaddr*)&client, &clientSize);
//if (clientSocket == INVALID_SOCKET) {
// wxLogMessage("Client Invalid Socket");
// return false;
//}
char host[NI_MAXHOST]; //Client's remote name
char service[NI_MAXHOST]; //Service (port) the client is connected on
ZeroMemory(host, NI_MAXHOST);
ZeroMemory(service, NI_MAXHOST);
if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0) {
wxLogMessage("Can't initialize Winsock! Quitting");
}
else {
inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
wxLogMessage(host);
int wut = client.sin_port;
wxString mystring = wxString::Format(wxT("%i"), wut);
wxLogMessage("Connected on port");
wxLogMessage(mystring);
//wxLogMessage(to_string(ntohs(client.sin_port)));
}
wxLogMessage("Got this far somehow");
//Close listening socket - we don't need it anymore - later on we'll learn how to accept multiple client
closesocket(listening);
//while loop: accept and echo message back to client
char buf[4096];
while (true)
{
ZeroMemory(buf, 4096);
//Wait for client to send data
int bytesReceived = recv(clientSocket, buf, 4096, 0);
if (bytesReceived == SOCKET_ERROR) {
//wxLogMessage("ERROR in recv");
break;
}
if (bytesReceived == 0) {
wxLogMessage("Client Disconnected");
break;
}
//Echo back to client
send(clientSocket, buf, bytesReceived + 1, 0);
//Close the socket
closesocket(clientSocket);
//Cleanup winsock
WSACleanup();
wxLogMessage("Welp");
}
}
// event handlers
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
// true is to force the frame to close
ServerStuff();
//Close(true);
}
On the YouTube video ("Creating a TCP Server in C++" - not allowed to post links) this works! The command window opens, is blank infinitely until he connects a client and then the client sends a message and the server replies with the same exact message in return.
Not mine. Mine just rushes through everything and then closes. My log used to immediately quit on the commented code where it states the client socket is invalid so I commented it out. Now my output is:
204.204.204.204
Connected on port
52428
Got this far somehow
I don't know what to do. I'm just trying to send data over a same-machine TCP connection. I'm baffled as to how this is so difficult. It seems like some random process is immediately trying to connect as a client to my server ? But why is it allowed to connect on port 52428 when I'm explicitly hosting on 54000?
My goal:
Start Server
Connect to Server using a Java App within BlueStacks
Send data from Server to Client
It makes more sense for the computer to be the server because there will be multiple BlueStacks instances and I'd prefer to not have to "spawn" multiple programs / servers for what I'm doing.
I see a few mistakes in your socket code.
not calling WSACleanup() if WSAStartup() is successful and then something goes wrong afterwards.
not calling closesocket() if socket() is successful and then something goes wrong afterwards.
not zeroing out the sockaddr_in that you pass to bind(). Random bytes in the struct can cause bind() to fail.
ignoring the return values of bind(), listen(), accept(), and send().
not treating the return value of getnameinfo() correctly. It returns 0 on success, not failure.
sending +1 extra byte back to the client than you received from the client. If the client sends fewer bytes than your buffer can hold, that extra byte would be 0x00 due to your ZeroMemory() call. But if the client actually sends enough bytes to completely fill your buffer, then you would send an extra byte from memory that you do not own. If you really want to send a null terminator after everything you echo, do so explicitly. Otherwise, a true echo server should only send back exactly what it receives, no more, no less.
Try something more like this:
void ServerStuff() {
WSADATA WsData;
int ret = WSAStartup(MAKEWORD(2, 2), &WsData);
if (ret != 0) {
wxLogMessage("Can't initialize Winsock! Error: %d", ret);
return;
}
//Create a socket
SOCKET listening = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listening == INVALID_SOCKET) {
wxLogMessage("Can't create a socket! Error: %d", WSAGetLastError());
WSACleanup();
return;
}
//Bind the ip and port to a socket
sockaddr_in hint = {};
hint.sin_family = AF_INET;
hint.sin_port = htons(54000);
hint.sin_addr.s_addr = INADDR_ANY; //Could also use inet_pton
ret = bind(listening, (sockaddr*)&hint, sizeof(hint));
if (ret == SOCKET_ERROR) {
wxLogMessage("Can't bind socket! Error: %d", WSAGetLastError());
closesocket(listening);
WSACleanup();
return;
}
//Tell winsock the socket is for listening
ret = listen(listening, SOMAXCONN);
if (ret == SOCKET_ERROR) {
wxLogMessage("Can't listen on socket! Error: %d", WSAGetLastError());
closesocket(listening);
WSACleanup();
return;
}
//Wait for a connection
sockaddr_in client = {};
int clientSize = sizeof(client);
SOCKET clientSocket = accept(listening, (sockaddr*)&client, &clientSize);
if (clientSocket == INVALID_SOCKET) {
wxLogMessage("Can't accept a client! Error: %d", WSAGetLastError());
closesocket(listening);
WSACleanup();
return;
}
char host[NI_MAXHOST] = {}; //Client's remote name
ret = getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, NULL, 0, 0);
if (ret != 0) {
wxLogMessage("Can't get client name info! Error: %d", ret);
inet_ntop(AF_INET, &(client.sin_addr), host, NI_MAXHOST);
}
wxLogMessage("Client: %s, Connected on port: %hu", host, ntohs(client.sin_port));
//Close listening socket - we don't need it anymore - later on we'll learn how to accept multiple client
closesocket(listening);
//while loop: accept and echo message back to client
char buf[4096];
int bytesReceived;
while (true)
{
//Wait for client to send data
bytesReceived = recv(clientSocket, buf, sizeof(buf), 0);
if (bytesReceived == SOCKET_ERROR) {
wxLogMessage("Can't read from client! Error: ", WSAGetLastError());
break;
}
if (bytesReceived == 0) {
wxLogMessage("Client Disconnected");
break;
}
//Echo back to client
ret = send(clientSocket, buf, bytesReceived, 0);
if (ret == SOCKET_ERROR) {
wxLogMessage("Can't send to client! Error: ", WSAGetLastError());
break;
}
}
//Close the socket
closesocket(clientSocket);
//Cleanup winsock
WSACleanup();
wxLogMessage("Welp");
}
I'm trying to read these incoming UDP packets using Wireshark:
I'm using the next code:
struct sockaddr_in si_other;
struct sockaddr_in remaddr; /* remote address */
int slen = sizeof(remaddr);
int s, recvlen;
char buf[BUFLEN];
char message[BUFLEN];
WSADATA wsa;
//Initialise winsock
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Initialised.\n");
//create socket
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == SOCKET_ERROR) //IPPROTO_UDP
{
printf("socket() failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
//setup address structure
memset((char *)&si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(PORT);
si_other.sin_addr.S_un.S_addr = inet_addr(SERVER);
if (bind(s, (struct sockaddr *)&si_other, sizeof(si_other)) < 0) {
perror("bind failed");
return 0;
}
u_long nMode = 1; // 1: NON-BLOCKING
if (ioctlsocket(s, FIONBIO, &nMode) == SOCKET_ERROR)
{
closesocket(s);
WSACleanup();
return 0;
}
//start communication
while (1)
{
printf("waiting on port %d\n", PORT);
if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == SOCKET_ERROR)
{
printf("recvfrom() failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Done");
puts(buf);
}
The address I'm binding is 192.168.1.1 and the port 1234.
And the given output by WSAGetLastError is an empty buffer error: 10035
I tried to disconnect firewall, antivirus...and I'm running the program as a administrator, and it didn't help.
Why is the buffer empty? I'm clearly seeing that there are packets coming, what could be blocking the incoming data to the socket?
the given output by WSAGetLastError() is an empty buffer error: 10035
No it isn't. 10035 is WSAEWOULDBLOCK. That means the operation would block in blocking mode, i.e. that no data was present to be received at the moment you called recvfrom().
The address I'm binding is 192.168.1.1
The IP 192.168.1.1 is shown as a gateway
These two statements are mutually inconsistent. If it's a gateway it's an external IP address, and if it's an external IP address you can't bind to it.
I tried INADDR_ANY and it didn't help
Not surprising. If you're not 192.168.1.1 you can't receive its messages. Unclear why you would think otherwise.
As #EJP mentioned 10035 is WSAEWOULDBLOCK, i.e., no data is ready. The cause of this is that the receiver is 192.168.1.1 which is your gateway's IP address, thus not a local IP. In this case you cannot receive the packets in a normal manner.
You can receive these packets, even though they are not meant for you, by using an UDP sniffer, e.g., using libpcap.
Thanks for the answers, they pointed me to the right direction. I 've got now the program working and I'm able to receive the incoming UDP packets.
The solution was to "sniff" these UDP packets, winsock allows that using the WSAIoctl function after bind, in my case adding the next code to the above program (after the bind function):
if (WSAIoctl(s, SIO_RCVALL, &j, sizeof(j), 0, 0, (LPDWORD)&si_other, 0, 0) == SOCKET_ERROR)
{
printf("WSAIoctl() failed.\n");
return 1;
}
I hope could help somebody else with similar issue.
i have problem because my server dont get UDP data. Ports on router are forwarded, data income to local-server network (it is visible on sniffer (3) ) but server dont receive it.
Server and server network screen
You can see 1 and 2 TCP packets correct income to server on connected sockets. But my client then send UDP data to server and data enter to local-server network (see that sniffer detect it on 3) but server dont take it.
Here is code of client:
struct sockaddr_in si_other;
int s, slen = sizeof(si_other);
char buf[10];
char message[10];
WSADATA wsa;
//Initialise winsock
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Initialised.\n");
//create socket
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR)
{
printf("socket() failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
//setup address structure
memset((char *)&si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(14996);
si_other.sin_addr.S_un.S_addr = inet_addr(server ip);
memcpy(message, "cokolwiek", 8);
//send the message
if (sendto(s, message, strlen(message), 0, (struct sockaddr *) &si_other, slen) == SOCKET_ERROR)
{
printf("sendto() failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
But its not problem with client. Here is server code but i think it is also correct:
SOCKET s;
struct sockaddr_in server, si_other;
int slen, recv_len;
char buf[10];
WSADATA wsa;
slen = sizeof(si_other);
//Initialise winsock
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Initialised.\n");
//Create a socket
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
{
printf("Could not create socket : %d", WSAGetLastError());
}
printf("Socket created.\n");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(14996);
//Bind
if (::bind(s, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
puts("Bind done");
//blocking on it, waiting for data
if ((recv_len = recvfrom(s, buf, 10, 0, (struct sockaddr *) &si_other, &slen)) == SOCKET_ERROR)
{
printf("recvfrom() failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
//print details of the client/peer and the data received
printf("Received packet from %s:%d\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port));
printf("Data: %s\n", buf);
Some description that may help - main server loop is select() and when client ask for order, server send order back to client and starts proceeding command.
server:
while (1) {
select()
if (socket is in FD_SET)
get data, send it back and handleCommand()
}
handleCommand() {
tcp data exchange
wait for udp packet - it fail
}
client:
sendCommand()
//another receiving commands thread
while (recv) {
handle command
tcp data exchange
send udp data
}
Pls dont give me answears to do it in another wait. I need to punch hole for NAT Traversal. What problem is that? Another listener grabbing my data? But netstat -nop UDP -a didn't give information that something other is listening, and bind socket didn't failed. Also another important information That code work on the begining of program, i mean server receive data but later not.
Okey, so as ElderBug said
Are you sure you setup the UDP server socket before you send the data ? It's not clear in your question
Yep, it was my fault. The miniseconds decided that sending data on one machine was executed before setting up listener on server. Thank you for answer.
But i dont exactly understand the problem. Shouldn't that data income to receive buffer and wait for "grabbing" it by recvfrom function?
I need help for my project. I not good at this. here are my server receiver. this coding is done for the physical pc. basically this coding in physical pc is to receive the data packet from the virtual receiver. It works. but somehow i had problem in decode the packet info and i noob at all this.
#define HAVE_REMOTE
#define MAX_BUF_SIZE 1024
#define snprintf _snprintf
#define ETH_ALEN 6
#define IP_ALEN 4
#define ARP_REQUEST 1
#define ARP_REPLY 2
#include <stdlib.h>
#include <stdio.h>
#include <winsock2.h>
#include <pcap.h>
#pragma comment(lib, "wpcap.lib")
#pragma comment(lib, "Ws2_32.lib")
// A sample of the select() return value
int recvfromTimeOutUDP(SOCKET socket, long sec, long usec)
{
// Setup timeval variable
struct timeval timeout;
struct fd_set fds;
timeout.tv_sec = sec;
timeout.tv_usec = usec;
// Setup fd_set structure
FD_ZERO(&fds);
FD_SET(socket, &fds);
// Return value:
// -1: error occurred
// 0: timed out
// > 0: data ready to be read
return select(0, &fds, 0, 0, &timeout);
}
int main(int argc, char **argv)
{
WSADATA wsaData;
SOCKET ReceivingSocket;
SOCKADDR_IN ReceiverAddr;
int Port = 5150;
char ReceiveBuf[6000];
int BufLength = 6000;
SOCKADDR_IN SenderAddr;
int SenderAddrSize = sizeof(SenderAddr);
int ByteReceived = 5, SelectTiming, ErrorCode;
char ch = 'Y';
// Initialize Winsock version 2.2
if( WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
{
printf("Server: WSAStartup failed with error %ld\n", WSAGetLastError());
return -1;
}
else
printf("Server: The Winsock DLL status is %s.\n", wsaData.szSystemStatus);
// Create a new socket to receive datagrams on.
ReceivingSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (ReceivingSocket == INVALID_SOCKET)
{
printf("Server: Error at socket(): %ld\n", WSAGetLastError());
// Clean up
WSACleanup();
// Exit with error
return -1;
}
else
printf("Server: socket() is OK!\n");
// Set up a SOCKADDR_IN structure that will tell bind that we
// want to receive datagrams from all interfaces using port 5150.
// The IPv4 family
ReceiverAddr.sin_family = AF_INET;
// Port no. 5150
ReceiverAddr.sin_port = htons(Port);
// From all interface (0.0.0.0)
ReceiverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
// Associate the address information with the socket using bind.
// At this point you can receive datagrams on your bound socket.
if (bind(ReceivingSocket, (SOCKADDR *)&ReceiverAddr, sizeof(ReceiverAddr)) == SOCKET_ERROR)
{
printf("Server: bind() failed! Error: %ld.\n", WSAGetLastError());
// Close the socket
closesocket(ReceivingSocket);
// Do the clean up
WSACleanup();
// and exit with error
return -1;
}
else
printf("Server: bind() is OK!\n");
// Some info on the receiver side...
getsockname(ReceivingSocket, (SOCKADDR *)&ReceiverAddr, (int *)sizeof(ReceiverAddr));
printf("Server: Receiving IP(s) used: %s\n", inet_ntoa(ReceiverAddr.sin_addr));
printf("Server: Receiving port used: %d\n", htons(ReceiverAddr.sin_port));
printf("Server: I\'m ready to receive a datagram...\n");
SelectTiming = recvfromTimeOutUDP(ReceivingSocket, 100, 0);
switch (SelectTiming)
{
case 0:
// Timed out, do whatever you want to handle this situation
printf("Server: Timeout while waiting for client!...\n");
break;
case -1:
// Error occurred, maybe we should display an error message?
// Need more tweaking here and the recvfromTimeOutUDP()...
printf("Server: Some error encountered with code number: %ld\n", WSAGetLastError());
break;
default:
{
while (1)
{
// Call recvfrom() to get it then display the received data...
ByteReceived = recvfrom(ReceivingSocket, ReceiveBuf, BufLength,
0, (SOCKADDR *)&SenderAddr, &SenderAddrSize);
if ( ByteReceived > 0 )
{
printf("\n\nServer: Total Bytes received: %d\n", ByteReceived);
printf("Server: The data is \"%s\"\n", ReceiveBuf);
}
else if ( ByteReceived <= 0 )
printf("Server: Connection closed with error code: %ld\n",
WSAGetLastError());
else
printf("Server: recvfrom() failed with error code: %d\n",
WSAGetLastError());
// Some info on the sender side
getpeername(ReceivingSocket, (SOCKADDR *)&SenderAddr, &SenderAddrSize);
printf("Server: Sending IP used: %s\n", inet_ntoa(SenderAddr.sin_addr));
printf("Server: Sending port used: %d\n", htons(SenderAddr.sin_port));
printf("TIME -", ReceiveBuf);
}
}
}
// When your application is finished receiving datagrams close the socket.
printf("Server: Finished receiving. Closing the listening socket...\n");
if (closesocket(ReceivingSocket) != 0)
printf("Server: closesocket() failed! Error code: %ld\n", WSAGetLastError());
else
printf("Server: closesocket() is OK...\n");
// When your application is finished call WSACleanup.
printf("Server: Cleaning up...\n");
if(WSACleanup() != 0)
printf("Server: WSACleanup() failed! Error code: %ld\n", WSAGetLastError());
else
printf("Server: WSACleanup() is OK\n");
// Back to the system
// system("PAUSE");
return 0;
}
Below are example i get in my CLI in physical pc. i believe this is the packets by packets receive from the virtual receiver. I was confused how do i decode it into
Time|Sender Mac Addr|Target Mac Addr|Packet Len|Ether Type|Src IP Addr| dest IP Addr
Server: Total Bytes received: 4000
Server: The data is "Time : 10:32:24.759385
0050568214540064403a1c000800450000285aeb40007f06b0c4ac10a40bac10f3f3c0990d3d740222860176142f5010054e40620000000000000000"
Server: Sending IP used: 172.16.243.243
Server: Sending port used: 59079
Server: Total Bytes received: 4000
Server: The data is "Time : 10:32:24.759385
0050568214540064403a1c000800450000285aeb40007f06b0c4ac10a40bac10f3f3c0990d3d740222860176142f5010054e40620000000000000000"
Server: Sending IP used: 172.16.243.243
Server: Sending port used: 59080
How do i decode the packet info analysis ?
decode it, something like this.
Time|Sender Mac Addr|Target Mac Addr|Packet Len|Ether Type|Src IP Addr| dest IP Addr
You presumably wrote the data to a byte buffer in order to send it. When receiving it you just need to read back the data in from your receive buffer the same way that you wrote it. We can only see your receive code so we can only guess what you send, but lets say for example that you write 4 x 4 byte integers to a char buffer and then send over the socket. The receiving code will need to do something like
int iData1 = 0;
int iData2 = 0;
int iData3 = 0;
int iData4 = 0;
char* szIt = ReceiveBuff; // set a pointer to start of receive buffer
memcpy(&iData1,szIt,sizeof(int); // memcpy first item
szIt += sizeof(int); // point to location in buffer of next item
memcpy(&iData2,szIt,sizeof(int); // memcpy second....
szIt += sizeof(int);
// Now do the rest of the data items until you have read
// everything in the packet
and so on for the next items. If you have different types then you need to increment the pointer by the size of those types. There are other ways you can do the same thing but this will work. A very important thing you need to consider when doing this is the endeanness of the machine you send on and receive from. You could enforce your data to write big endean so that the client knows and can deal with it if it is itself little endean.
The important thing is the order of the data you send and to interpret your byte buffer the same way on the client end.
Hope this helps