Winsock 1.1 help getting remote clients ip address :/

Started by
6 comments, last by yewbie 15 years, 7 months ago
Im trying to write a server program and a client program just to mess around and learn winsock with... well im having a problem, I can get the client to connect I can even send data but when I try to get the ip address it does not come out correctly :/ here is what im using to try to output the ip address

sockaddr_in NewRemoteSin;
SOCKET newsock = accept(sock, (sockaddr*)&NewRemoteSin, NULL);
/* NOTE: Now NewRemoteSin contains the address of the new client. And newsock contains the socket that has the new connection */ 
WSAAsyncSelect(newsock, hWndMain, WM_USER + 2, FD_READ | FD_CLOSE);
cout << "Client Connected - " << NewRemoteSin.sin_addr.S_un.S_addr <<"\n" ;			



but all this does is display some numbers that are not even close to the ip address :/ any tips ? below is the whole code for the server main.cpp

//Our WinSockTest Application WinSockText.cpp
#include "WinSockTest.h"



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////  **      **      ** **  **    **  **     **  ******  **   **    **
////////////  **    ****    **  **  ****  **  **** ****  **  **  **   ****  **
/////////////  **  **  **  **   **  ** ** **  ** **  **  ******  **   ** ** **
//////////////  ****    ****    **  **  ****  **     **  **  **  **   **  ****
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//This is our main Windows thread with all the other stuff

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
	
	WNDCLASSEX wcx;//create window class
	wcx.cbSize=sizeof(WNDCLASSEX);//set the size of the structure
	wcx.style=CS_OWNDC | CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;//class style
	wcx.lpfnWndProc=TheWindowProc;//window procedure
	wcx.cbClsExtra=0;//class extra
	wcx.cbWndExtra=0;//window extra
	wcx.hInstance=hInstance;//application handle
	wcx.hIcon=LoadIcon(NULL,IDI_APPLICATION);//icon
	wcx.hCursor=LoadCursor(NULL,IDC_ARROW);//cursor
	wcx.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);//background color
	wcx.lpszMenuName=NULL;
	wcx.lpszClassName="WINXCLASS";//class name
	wcx.hIconSm=NULL;//small icon
	if(!RegisterClassEx(&wcx)) return(0);//register the window class, return 0 if not successful
		
	//create main window
	hWndMain=CreateWindowEx(NULL,"WINXCLASS","Server Test", WS_VISIBLE | WS_SYSMENU | WS_MINIMIZEBOX | WS_CAPTION ,0,0,500,500,NULL,NULL,hInstance,NULL);
	
	//Setup our buttons
	CreateWindow("Button","Start Server",WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,0,150,125,25,hWndMain,(HMENU) BUTTON_STARTSERVER,hInstance,NULL);//Make our start server button  
	CreateWindow("Button","ShutDown Server",WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,0,175,125,25,hWndMain,(HMENU) BUTTON_SHUTDOWNSERVER,hInstance,NULL);//Make our End Server Button
	
	//error check returns true if our main window failed to create
	if(!hWndMain) return(0);
	
	//Server_Init
	ServerInit();
	
	MSG msg;//declare our message pump
	for(;;)	
	{
		//look for a message
		if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
		{
			//check that we arent quitting
			if(msg.message==WM_QUIT) break;
			//translate message
			TranslateMessage(&msg);
			//dispatch message
			DispatchMessage(&msg);
			
		}
		//Server_Running();
		
	}
	ServerShutDown();
	

	return(0);
}



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////WINDOWS MESSAGES PROC///////////////////////////////////
/////////////////////////////////////////////////////////////////////////////

LRESULT CALLBACK TheWindowProc(HWND hWndMain,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
		
	//which message did we get?
	switch(uMsg)
	{
		
		case WM_COMMAND:
			{
				int wmId, wmEvent;
				wmId    = LOWORD(wParam); 
				wmEvent = HIWORD(wParam); 
				// Parse the menu selections:
				switch (wmId)
					{
						//Start Server button was clicked
						case BUTTON_STARTSERVER:
							{
								ServerStart();
							}break;
						case BUTTON_SHUTDOWNSERVER://Shut Down Server Button was clicked
							{
								PostQuitMessage(0); //break our message loop
							}break;
						default:
						break;
					}//switch (wmId) end brace
			}break;//WM_COMMAND
		case SERVER_SOCKET: 
			HandleData(wParam, lParam); break; 
		case WM_DESTROY://the window is being destroyed
			{
				PostQuitMessage(0);//tell the application we are quitting
				return(0);//handled message, so return 0
			}break;//WM_DESTORY
		case WM_PAINT://the window needs repainting
			{
				PAINTSTRUCT ps;//a variable needed for painting information
				HDC hdc=BeginPaint(hWndMain,&ps);//start painting
				EndPaint(hWndMain,&ps);//end painting
				return(0);//handled message, so return 0
			}break;//WM_PAINT
	}
	//pass along any other message to default message handler
	return(DefWindowProc(hWndMain,uMsg,wParam,lParam));
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Server Init
void ServerInit()
{
	InitConsoleShell(); //turn on our console
	





	cout << "Server Init Complete\n";
	return;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Server Shut Down
void ServerShutDown()
{
	WSACleanup();
	cout << "Server Shutdown Complete\n";
	Sleep(2000);
	return;
}

/////////////////////////////////////////////////////////////////
//This starts up our server
void ServerStart()
{
	InitWinSock();


}

void InitWinSock()//our winsock startup stuff
{
	WSAData wsa;  //our winsock structure
	sockaddr_in sin; //our socket in address structure
	SOCKET sock; //our socket structure
	char MyHostName[80];

	WSAStartup(MAKEWORD(1, 1), &wsa); //fill out our wsa structure
	
	if((sock = socket(PF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR) //allocate our socket
		{
			//socket failed to allocate something is wrong
			cout << "socket failed to allocate something is wrong ERROR:" << WSAGetLastError() << endl;
			return;
		}
	
	sin.sin_family = AF_INET; /* Set the family for the socket to internet */
	sin.sin_port = htons(4444);/* Set to use port 4444 */ 
	//sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); /* IP ADDRESS */ //probably don't need this
	sin.sin_addr.S_un.S_addr = htonl(INADDR_ANY); /* IP ADDRESS */ //probably don't need this
	if(bind(sock, (sockaddr *)&sin, sizeof(sockaddr_in)) == SOCKET_ERROR) //try to bind our socket
		{
			//socket failed to bind something is wrong
			cout << "socket failed to bind something is wrong ERROR:" << WSAGetLastError() << endl;
			return;
		}

	if(listen(sock, 200) == SOCKET_ERROR) //start listening
		{
			//socket failed to start listening
			cout << "Socket Failed to listen ERROR:" << WSAGetLastError() << endl;
			return;
		}
	WSAAsyncSelect(sock, hWndMain, SERVER_SOCKET, FD_ACCEPT | FD_CLOSE | FD_READ); //set our socket to non blocking mode accepting connections telling us when they close and when we have info to read
	
	if(gethostname(MyHostName, sizeof(MyHostName)) == SOCKET_ERROR)  //get our hostname
	{
		cout << "Error Getting Host Name: ERROR:" << WSAGetLastError() << endl;
		return;
	}

	struct hostent *phe = gethostbyname(MyHostName); //do a host name look up
    if (phe == 0) 
	{
        cerr << "Could not look up hostname!!" << endl;
        return;
	}

	struct in_addr addr; //setup our ip address struct
	memcpy(&addr, phe->h_addr_list[0], sizeof(struct in_addr)); //copy our ip address to the struct
    
	cout << "Winsock initilization complete (Hostname:" << MyHostName << " IP:" << inet_ntoa(addr) << ")\n";
}


/////////////////////////////////////////////////////////////////////
int HandleData(WPARAM wParam, LPARAM lParam) 
{ 
	SOCKET sock =	(SOCKET)wParam;//this is our server socket
	WORD event =	LOWORD(lParam);
	WORD error =	HIWORD(lParam);
	if(event == FD_CLOSE)
		{ 
			cout << "FD_CLOSE - Socket Closed\n";
			closesocket(sock);
		} 
	else if(event == FD_READ) 
		{ 
			char szBuffer[1024];
			ZeroMemory(szBuffer, 1024);
			recv(sock, szBuffer, 1024, 0);
			cout << "FD_READ - Received Data\n";
			closesocket(sock);
		}
	else if(event == FD_ACCEPT)
		{ 
			sockaddr_in NewRemoteSin;
			SOCKET newsock = accept(sock, (sockaddr*)&NewRemoteSin, NULL);
			//AcceptEx(sock, newsock
			/* NOTE: Now NewRemoteSin contains the address of the new client. And newsock contains the socket that has the new connection */ 
			WSAAsyncSelect(newsock, hWndMain, WM_USER + 2, FD_READ | FD_CLOSE);
			//send(newsock, "Hello, welcome to my server.", strlen("Hello, welcome to my server."), 0); 
			
			//text sending a struct
			datastruct.hexbyte = 0x01;
			strcpy (datastruct.text, "test 0x01");
			send(newsock, (char*)&datastruct, sizeof(DATASTRUCT), 0);
						
			cout << "FD_ACCEPT - Client Connected - " <<  sock <<"\n" ;
			cout << "FD_ACCEPT - Client Connected - " <<  newsock <<"\n" ;
			//cout << "FD_ACCEPT - Client Connected - " <<  inet_addr(NewRemoteSin.sin_addr.S_un) <<"\n" ;
			cout << "FD_ACCEPT - Client Connected - " << NewRemoteSin.sin_addr.S_un.S_addr <<"\n" ;
			
		} 
	return TRUE; 
}


////////////////////////////////////////////////////////////////////
//Console Shell
void InitConsoleShell()
{
	int hConHandle;
	long lStdHandle;
	CONSOLE_SCREEN_BUFFER_INFO coninfo;
	FILE *fp;
	AllocConsole();
	SetConsoleTitle("Server");


	 // set the screen buffer to be big enough to let us scroll text
	GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),	&coninfo);
	coninfo.dwSize.Y = MAX_CONSOLE_LINES;
	SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),	coninfo.dwSize);
	// redirect unbuffered STDOUT to the console
	lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
	fp = _fdopen( hConHandle, "w" );
	*stdout = *fp;
	setvbuf( stdout, NULL, _IONBF, 0 );
	// redirect unbuffered STDIN to the console
	lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
	fp = _fdopen( hConHandle, "r" );
	*stdin = *fp;
	setvbuf( stdin, NULL, _IONBF, 0 );
	// redirect unbuffered STDERR to the console
	lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
	fp = _fdopen( hConHandle, "w" );
	*stderr = *fp;
	setvbuf( stderr, NULL, _IONBF, 0 );
	// make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog point to console as well
	ios::sync_with_stdio();
	return;



WinSockTest.h

/our WinSockTest header file

#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#include <iostream>
#include <io.h>
#include <fcntl.h>
#include <winsock.h> //winsock include

#pragma comment(lib, "wsock32.lib") //winsock include

using namespace std;

//Defines
static const WORD MAX_CONSOLE_LINES = 5000; 
HWND hWndMain=NULL;//handle to our main window

//Button Defines for windows messaging
#define BUTTON_STARTSERVER 10001
#define BUTTON_SHUTDOWNSERVER 10002
#define SERVER_SOCKET WM_USER + 1
//ProtoTypes
LRESULT CALLBACK TheWindowProc(HWND hWndMain,UINT uMsg,WPARAM wParam,LPARAM lParam);
void ServerInit();
void ServerShutDown();
void ServerStart();
void InitConsoleShell(); //our console for text output
void InitWinSock();//our winsock startup stuff
int HandleData(WPARAM wParam, LPARAM lParam); //handle our winsock datagram

//Struct
 struct DATASTRUCT
 {
	BYTE hexbyte; //our hex (0x01) or whatever
	char text[1023];
	
 } datastruct;



Advertisement
FD_ACCEPT - Client Connected - 3435973836

is what I get when I connect a client thats not my ip address :(
The right way to do it: inet_ntoa(addr.sin_addr)

Where addr is your sockaddr_in structure used in accept. This will return a char*.
Note that WSAAsyncSelect(), and WSAEventSelect(), are low-performing, old-school Windows-only mechanisms to do sockets. There are a lot of restrictions on what you can do within the callback message handlers, for example. You will probably have an easier time getting things to work right, and finding tutorials, with good-old select() (which is cross platform), or by using I/O Completion Ports for sockets I/O (if you want to be Windows specific, but high performance).
enum Bool { True, False, FileNotFound };
Well the tutorial I found was for winsock 1.1 (it was written extremely well)
most of the tutorials I have seen for winsock 2 tend to jump around so much... and they don't go into alot of detail, do you have any suggestions as far as a tutorial or some reading?
here is what im looking to do:
-Have a server accept many simultaneous connections (100ish or more)
-Runs in windows(I'm still not to the programming step where I even try multi platform...)
-can send a data struct relatively easily between sockets
-tracking information would be helpful I couldn't find much on how to check mac addresses or anything useful from inside of winsock :/

basically server with the ability to talk with multiple clients.. and I also don't want to use a wrapper or some library that is not free or has some weird license attached to it

(sorry about all the requirements, my goal is to make something made by me for me and a few people I know to mess around with =p)
Quote:Original post by Escarab
The right way to do it: inet_ntoa(addr.sin_addr)

Where addr is your sockaddr_in structure used in accept. This will return a char*.


Thanks for the tip!

when I do that on my address if I connect locally on the same computer with client and server it returns 204.204.204.204 shouldn't it return like 127.0.0.1 or my computers ip address?
You are passing NULL to the last of the accept's arguments, you must pass the address of an int holding the size of your sockaddr_in structure.

Something like:
 sockaddr_in addr;    int legth=sizeof(addr);    SOCKET s=accept(listen_socket,(sockaddr*)&addr,&legth);


The most efficient way to deal with lots and lots of simultaneous clients is by using IOCP. IOCP is a complex thing, tough, and even more complex is make it work right.

Some links you my find useful:

winsock basic tutorial
IOCP basic tutorial
IOCP basic tutorial(another)

And don't forget of the good old MSDN.
Quote:Original post by Escarab
You are passing NULL to the last of the accept's arguments, you must pass the address of an int holding the size of your sockaddr_in structure.


You sir are genius thanks! it works perfectly now, not sure why I was passing null to begin with... might had had a compiler error with the way I was setting the size before and just made it null to just get it to compile and never fixed it =p

This topic is closed to new replies.

Advertisement