Hello everyone,

I am dealing with this problem that I receive a buffer from a client, and when I try to output what the client sends to my program, it only shows everything till the first zero character.

#include <cstdio>
#include <winsock2.h>
#include <iostream>
#include <string>

using namespace std;

struct incSockets
{
	SOCKET sv;
	SOCKET cl;
};

void filter(char* packet)
{
	while(*packet != 0)
	{
		cout << "(" << int(*packet) << ")";
		packet++;
	}
		
	cout << endl;
}

int main(int argc, char** argv) {

	struct incSockets incs;

	const int iReqWinsockVer = 2;   

	WSADATA wsaData;

	if (WSAStartup(MAKEWORD(iReqWinsockVer,0), &wsaData)==0)
	{
		if (LOBYTE(wsaData.wVersion) >= iReqWinsockVer)
		{
			incs.cl = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);	
			size_t bytesReceived;
			
			if (incs.cl==INVALID_SOCKET)
			{
				//error
			}
							
			sockaddr_in clSockAddr;
			
			memset(&clSockAddr, 0, sizeof(clSockAddr));
			
			clSockAddr.sin_family = AF_INET;
			clSockAddr.sin_port = htons(1339);
			clSockAddr.sin_addr.S_un.S_addr = INADDR_ANY;

			if (bind(incs.cl, (sockaddr*)(&clSockAddr), sizeof(clSockAddr))!=0)
			{
				//error	
			}
			
			char buffer[1024];
			int fromlen = 10240;

			while(true) {
				bytesReceived = recvfrom(incs.cl, buffer, 1024, 0, (struct sockaddr *)&clSockAddr, &fromlen);
				
				if(bytesReceived < 0) {
					//error
				}
				
			
				//When I do this, it shows me way more. 
				//cout << int(buffer[0]) << int(buffer[1]) << int(buffer[2]) << int(buffer[3]) << int(buffer[4]) << int(buffer[5]) << int(buffer[6]) << int(buffer[7]) << endl;
				
				//Now it only shows me the first 5 characters. The sixth is a 0.
				filter(buffer);
			}
			
			closesocket(incs.cl);
		}
		else
		{
			// Required version not available
		}

		// Cleanup winsock
		if (WSACleanup()!=0)
		{
			// cleanup failed
		}
	}
	else
	{
		//  startup failed
	}
    return 0;
}

I hope someone can help me solve this problem.

Thanks in advance.

Recommended Answers

All 50 Replies

void filter(char* packet)
{
	while(*packet != 0)
	{
		cout << "(" << int(*packet) << ")";
		packet++;
	}	
	cout << endl;
}

Hi, I've never written a program like this before, but look at the condition you place on the loop : while(*packet != 0) That'll stop whenever *packet == 0

How should I finish the while-loop in that case.
When you got

int i = {1, 2, 3, 4};
int* p = i;

When you loop that with the filter function it will show: (1)(2)(3)(4) or something like it.

If I don't do the != 0 it will show
(1)(2)(3)(4) followed by a lot of errors and finally a crashing program.

How would I be able to solve that?

use a for loop.

What should the conditions of this for-loop be in that case?

Thank you both for responding by the way.

If I am reading correctly, you want to show packet as an int, via this
function?

void filter(char* packet)
{
	while(*packet != 0)
	{
		cout << "(" << int(*packet) << ")";
		packet++;
	}	
	cout << endl;
}

That's correct, yes.

Is the string a char of digits or characters?

void filter(char* packet)
{
    int i = 0;
	while(packet[i])
	{
		cout << "(" << int(packet[i]) << ")";
		i++;
	}	
	cout << endl;
}

never mind what i'm saying

That still doesn't work, it prints the first 5 characters, but not the following characters.

Currently it prints
(83)(65)(77)(80)(127)
which means:
SAMP and the 127 is the start from my local IP, which should be (127)(0)(0)(1).

Then your problem is the buffer thats being passed to it. I does
not contain what you want.

I assume that the problem is here:

bytesReceived = recvfrom(incs.cl, buffer, 1024, 0, (struct sockaddr *)&clSockAddr, &fromlen);

Check if bytesReceived is the correct number of bytes you want to recieve.

Sorry, i shouldn't be trying to answer this-I'm just confusing things with my nonsense responses.

when I do

void filter(char* packet)
{

	for(int i = 0; i < 8; i++)
	{
		cout << "(" << int(*packet) << ")";
		packet++;
	}
		
	cout << endl;
}

It print's
(83)(65)(77)(80)(127)(0)(0)(1)
though, so that would mean the buffer contains that information right?

"will evaluate to false when packet==0"

Yes thats correct. The 0 identifies the end of the string. Any further
then its junk.

When I cout the receivedBytes I get this number 4294967295. Would this be right?

"will evaluate to false when packet==0"

Yes thats correct. The 0 identifies the end of the string. Any further
then its junk.

Sorry, I didn't understand the original post at first. I shouldn't have posted anything.

when I do

void filter(char* packet)
{

	for(int i = 0; i < 8; i++)
	{
		cout << "(" << int(*packet) << ")";
		packet++;
	}
		
	cout << endl;
}

It print's
(83)(65)(77)(80)(127)(0)(0)(1)
though, so that would mean the buffer contains that information right?

Thats weird. Try cout<<buffer before the function call , and in the function as well. See if they are the same.

I think you're all missing the point. Sockets doesn't send immediately.

Send Packet 5
Send Packet 8
Send Packet 7

It won't necessarily arrive as three packets 5 then 8 then 7 bytes in length.
It may arrive as 2 packets 5+8=13 and 7
or 5 and 15
or a single packet 20 bytes long!
The packet is sent on an interval basis, not immediately so sometimes packets get combined as a single packet of multiple messages!

So instead!

void filter( char* packet, uint nPacketLen )
{
    while (nPacketLen)
    {
         while ((*packet != 0) && nPacketLen)
        {
	cout << "(" << int(*packet) << ")";
               packet++;
               nPacketLen--
       }
        cout << endl;
   }
}

thanks wild goose. Haven't worked with socket.

@firstPerson:
Outputting the buffer before and in the function gives the same output.

@wildgoose:
Where nPacketLen would be bytesReceived?

Yes! That's the number of bytes received in the packet. Packets aren't cut in half, they are delivered whole! So your packet will contain one or more messages!

The meaning of my program in the end will be to make a simple packetsniffer.

Client -> My Program -> Server

However, the packets aren't received fully, or I can't display them fully, so I can't send them to the client or server fully either.


Currently I have this, which gives me no output at all:

#include <cstdio>
#include <winsock2.h>
#include <iostream>
#include <string>

using namespace std;

struct incSockets
{
	SOCKET sv;
	SOCKET cl;
};

void filter( char* packet, int nPacketLen )
{
    while (nPacketLen)
    {
        while ((*packet != 0) && nPacketLen)
        {
			cout << "(" << int(*packet) << ")";
            packet++;
            nPacketLen--;
       }
       cout << endl;
   }
}

int main(int argc, char** argv) {

	struct incSockets incs;

	const int iReqWinsockVer = 2;   

	WSADATA wsaData;

	if (WSAStartup(MAKEWORD(iReqWinsockVer,0), &wsaData)==0)
	{
		if (LOBYTE(wsaData.wVersion) >= iReqWinsockVer)
		{
			incs.cl = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);	
			size_t bytesReceived;
			
			if (incs.cl==INVALID_SOCKET)
			{
				//error
			}
							
			sockaddr_in clSockAddr;
			
			memset(&clSockAddr, 0, sizeof(clSockAddr));
			
			clSockAddr.sin_family = AF_INET;
			clSockAddr.sin_port = htons(1339);
			clSockAddr.sin_addr.S_un.S_addr = INADDR_ANY;

			if (bind(incs.cl, (sockaddr*)(&clSockAddr), sizeof(clSockAddr))!=0)
			{
				//error	
			}
			
			char buffer[1024];
			int fromlen = 10240;

			while(true) {
				bytesReceived = recvfrom(incs.cl, buffer, 1024, 0, (struct sockaddr *)&clSockAddr, &fromlen);
		
				if(bytesReceived < 0) {
					//error
				}
				
			
				//When I do this, it shows me way more. 
				//cout << int(buffer[0]) << int(buffer[1]) << int(buffer[2]) << int(buffer[3]) << int(buffer[4]) << int(buffer[5]) << int(buffer[6]) << int(buffer[7]) << endl;
				
				//Now it only shows me the first 5 characters. The sixth is a 0.
				filter(buffer, bytesReceived);
			}
			
			closesocket(incs.cl);
		}
		else
		{
			// Required version not available
		}

		// Cleanup winsock
		if (WSACleanup()!=0)
		{
			// cleanup failed
		}
	}
	else
	{
		//  startup failed
	}
    return 0;
}

1st check that buffer length!
int fromlen = 10240; Your buffer is char buff[ 1024 ] not 10240.

that shouldn't be your problem but it is a problem!

Do a zero check!
Returning a vaue of zero bytes received is valid! It just means socket timed out waiting with no bytes received!

if ( bytesReceived > 0)
    filter(buffer, bytesReceived);

Put an error handler on bind()

Also on socket() though you aren't liable to run out of sockets!

Okay, I'm a little unclear about something.
You create the socket
You bound it to an address
but you aren't listening for a connection. Only a received message.
I normally don't setup sockets this way but from your earlier messages you indicated you were receiving five characters and now none!

Is the sending application still sending messages?

Alright, I've done so, it saved me a lot of spam when booting the program.

However, it still shows me only the first 5 packets with the filter-function.

I've also tried this: cout << buffer << endl; which gives me SAMP∆
int(∆) = 127 for(int i = 0; i < 8; i++) cout << int(buffer[i]); gives (83)(65)(77)(80)(127)(0)(0)(1) though.
What would be SAMP∆ 1

Yes, it is still sending messages.
After some time googeling I found that the UDP-protocol works diffrent than the TCP-protocol, hence the reason you don't have to listen for a connection. That would be the diffrence between UDP and TCP.

Do you have a raw dump of what's being sent!

Did you catch my last second buffer posting of 1024 vs 10240.


)(127)(0)(0)(1)

127.0.0.1

Is someone sending the Local IP as text!

Yes, I have changed it.

About the raw dump, I guess you mean, receiving and directly cout'ing it?

This is a handy function to keep around. I have it embedded in my file logging system.

Use it to dump your incoming buffer.
I've twiddled it for the post and replace RawPrint as your cout or other printf type mechansim!

//
//  Memory Dump
//
#define xMEM_DUMP_PAD	"      "
#define LOG_BUF_MAX   1024

void Mem( const void * const vp, uint nSize, const char *szText, ... )
{
    uint  x, run, tail, col, nOffset, nAddr;
    char *p, *r, *s, buf[256], *pStr;
    byte *mp;
	bool flg;

 		// If provided, write out the title

	if ( NULL != szText )
	{
		char	buff[ LOG_BUF_MAX ];
		va_list	args;

		va_start( args, szText ); 
		vsprintf(buff, szText, args);
		va_end( args );
		RawPrint(buff);					// Print a Banner
		flg = false;
	}
	else
	{
		flg = true;
	}

		//	Sub-Header

	sprintf(buf, "  Memory Dump: 0x%8.8x   Size: 0x%x (%u)\n", (uint)vp, nSize, nSize );
	RawPrint(buf);

		//	Memory Dump (Old DOS debug method)

    mp = (byte *) vp;

    run = 16;
	nAddr = (uint) (byte*)vp;
	
	strcpy(buf, xMEM_DUMP_PAD);
	pStr = buf + sizeof(xMEM_DUMP_PAD) - 1;

        //  For all lines

    for ( nOffset = 0; nOffset < nSize;  )
      {
	    col = tail = 0;
		p = pStr;

        p += sprintf(p, "%8.8x ", nOffset );
		r = p + (16*3 + 3 + 2);
		s = r + 16;
	
        if ( nSize-nOffset < run )
          {
            run = nSize-nOffset;						// Display only that requested!
            tail = 16 - run;							// trailing places
          }

		memset(p, ' ', s-p);
	
            //  Hex values

        for ( x = 0; x < run; x++, mp++ )
          {
            p += sprintf( p, " %2.2x", *mp );

				//	ASCII chars

            if (( 0x20 <= *mp ) && ( *mp <= 0x7f ))
              {
                *r++ = *mp;
              }
            else
              {
                *r++ = '.';
			  }

            if (( ++col % 4 ) == 0 )
              {
                *p++ = ' ';
              }
          }

		*p = ' ';										// Hex - ASCII fill

		s += sprintf( s, "  {0x%8.8x}\n", nAddr );

        RawPrint( buf );

		nAddr += run;									// (Real) Address - next text line
		nOffset += run;									// Offset - next text line
      }

    RawPrint( "\r\n" );
}

Yes, my client connects to localhost. Hence the 127.0.0.1.

What parameters should I pass trough to your function?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.