Skip to main content
GameDev.net gamedev.net
🔒 Locked

Adding UDP Functionality?

Started by neilski_2003 Jan 23, 2006 at 12:17 PM 1 replies 500+ views
Original Post
neilski_2003
neilski_2003
Hi guys, I have finally figured out the problem in the strange server thread and now everything works correctly. However - i would like to add in a UDP socket so that a client could broadcast to find it. I know how to set up a UDP socket with SOCK_DGRAM and all that but i was wondering how i would implement it within my code. Basically i just want it there listening so if a client sends a packet it responds to it with the IP address and Port number of the server so a TCP connection can be generated. Heres the code below.


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

using namespace std;

struct ClientEntry
	{
	int	socket_Number;		// Socket Number for TCP inbound connection
	sockaddr_in	Sender;	    // Details of socket
	} ;

#define	MAX_CLIENTS	5
ClientEntry	ClientEntryList[MAX_CLIENTS];

void SendServerMessage(char *message, ClientEntry from)
{
	char	completeMessage[512];
	int	m;

	sprintf(completeMessage, "[%s:%1d]: %s", inet_ntoa(from.Sender.sin_addr), ntohs(from.Sender.sin_port), message);
				

	for (m=0; m<MAX_CLIENTS; m++)			// Send it to all other clients
		if (ClientEntryList[m].socket_Number!=-1)
		{
			send(ClientEntryList[m].socket_Number, completeMessage, strlen(completeMessage), 0);
		}
}

int main()
{
	WSAData Wsadata;

	int l;
	int size;
	int error;
	int	MaxSocketNumber = -1;
	int Senderlen;
	int Temp;

	SOCKET serverTCP;
	SOCKET Client;
	sockaddr_in Server;
	sockaddr_in Sender;


	fd_set socketSet;


	char message[256];

	WSAStartup(MAKEWORD(2,2), &Wsadata);


	serverTCP = socket(AF_INET, SOCK_STREAM, 0);

	if (serverTCP==INVALID_SOCKET)
	{
		printf("Socket Creation Failed");
		return 0;
	}
	else
	{
		cout<<"Socket Created \n";
	}

	Server.sin_family=AF_INET;
	Server.sin_addr.s_addr=INADDR_ANY;
	Server.sin_port=htons(2222);


	Temp = bind(serverTCP, (sockaddr *) &Server, sizeof(Server));

	if(Temp == SOCKET_ERROR)
	{
		Temp = WSAGetLastError();
		printf("Binding Failed");
		WSACleanup();
		return 0;
	}
	else
	{
		cout<<"Socket Bound \n";
	}

	listen(serverTCP, SOMAXCONN);

	if(Temp == SOCKET_ERROR)
	{
		Temp = WSAGetLastError();
		printf("Binding Failed");
		WSACleanup();
		return 0;
	}
	else
	{
		cout<<"Socket Listening \n";
	}

	for (l=0; l<MAX_CLIENTS; l++)
	{
		ClientEntryList[l].socket_Number = -1;			
	}

	while (true)// continuous loop for the body of the server
	{							

		FD_ZERO(&socketSet);						// Empty the read set
		FD_SET(serverTCP, &socketSet);						// Add the Listening Socket
		MaxSocketNumber = serverTCP;

		for (l=0; l<MAX_CLIENTS; l++)
		{
			if (ClientEntryList[l].socket_Number!=-1)
			{
				FD_SET(ClientEntryList[l].socket_Number, &socketSet);	// add the client to the set of read sockets
				if (ClientEntryList[l].socket_Number>MaxSocketNumber)
				{
					MaxSocketNumber = ClientEntryList[l].socket_Number;//update the max socket number
				}
			}
		}

		error = select(MaxSocketNumber+1, &socketSet, 0, 0, 0);// Wait until something happens on any of the connected sockets		
										

		if (error<0) 
		{
			perror("select");					// Error with Select call itself
			break;
		}
		

		if (FD_ISSET(serverTCP, &socketSet))//a new connection is waiting
		{					
			Senderlen = sizeof(Sender);			

			Client = accept(serverTCP, (sockaddr *)&Sender, &Senderlen);		
																
			printf("New Client IP Address %s Port %1d\n", inet_ntoa(Sender.sin_addr), ntohs(Sender.sin_port));
			

			for (l=0; l<MAX_CLIENTS; l++)
			{
				if (ClientEntryList[l].socket_Number==-1)
				{
					ClientEntryList[l].socket_Number = Client;	
					memcpy(&ClientEntryList[l].Sender, &Sender,
					sizeof(Sender));	
					break;				
				}

				if (l==MAX_CLIENTS)// Do this if no free client spaces
				{					
					strcpy(message, "There are currently no available slots - Please Try Later\n");
					send(Client, message, strlen(message), 0);
					closesocket(Client);	
				}
			}

			continue;						// Restart While Loop
		}

		for (l=0; l<MAX_CLIENTS; l++)
		{
			if (ClientEntryList[l].socket_Number!=-1)
			{
				if (FD_ISSET(ClientEntryList[l].socket_Number, &socketSet))	// This client!
				{	
					size = recv(ClientEntryList[l].socket_Number, message, 255, 0);

					if (size>0)
					{					// A message!
						message[size] = 0;
						// Display sender and message
						printf("[%s] sends: %s\n", inet_ntoa(ClientEntryList[l].Sender.sin_addr), message);
						SendServerMessage(message, ClientEntryList[l]);		// Send to all clients
					}

					else
					{
						ClientEntryList[l].socket_Number = -1;		// Client exception error
						printf("Client %s has left\n", inet_ntoa(ClientEntryList[l].Sender.sin_addr));
						SendServerMessage("Client has Left\n", ClientEntryList[l]);
					}						// i.e. Client has left
				}
			}
		}
	}

	for (l=0;l<MAX_CLIENTS; l++)
	{
		if (ClientEntryList[l].socket_Number!=-1)
		{
				closesocket(ClientEntryList[l].socket_Number);
		}
	}

	closesocket(serverTCP);
	
	WSACleanup();

	return 0;
}

[\source]

Is it simply a case of putting a UDP socket in there and letting it do its stuff?

Cheers

Neil
hplus0603
hplus0603
Your question was hard to comprehend.

Is it the case that you have a working client/server set-up, but now you want to add local server discovery to the clients?

To do that, the easiest way is to open a UDP socket on each client, listening on port X, and opening a UDP socket on the server, binding it to the same port, turning on SO_BROADCAST, and sending the message to the broadcast address on the same port.

Btw: the data you put into the sprintf() probably shouldn't be converted with htons(), as someone will parse it out using text scanning, and then call htons() on it to get the right number -- if the client doing that is the other byte order from the server, it won't actually work out right! ASCII text is already a byte-order-independent representation.
enum Bool { True, False, FileNotFound };
neilski_2003
neilski_2003
Having read my question again it is, as you pointed out, a bit difficult to understand.

Basically I have a server that i wish to recieve both TCP and UDP messages.
At the moment the TCP works fine and does everything i want it to do, however despite adding a UDP socket it won't seem to recieve any messages on that socket.

I will include below both my server and Client code (which is probabaly very badly writen and goes against most rules of good programming). Am I initialising the sockets wrong or setting up the wrong ports or something?

Heres The Server:

#include <winsock2.h>#include <iostream>#include <string>using namespace std;struct ClientEntry	{	int	socket_Number;		// Socket Number for TCP inbound connection	sockaddr_in	Sender;	    // Details of socket	int Count;	} ;#define	MAX_CLIENTS	5ClientEntry	ClientEntryList[MAX_CLIENTS];void SendServerMessage(char *message, ClientEntry from){	char	completeMessage[512];	int	m;	sprintf(completeMessage, "[%s:%1d]: %s", inet_ntoa(from.Sender.sin_addr), ntohs(from.Sender.sin_port), message);					for (m=0; m<MAX_CLIENTS; m++)			// Send it to all other clients		if (ClientEntryList[m].socket_Number!=-1)		{			send(ClientEntryList[m].socket_Number, completeMessage, strlen(completeMessage), 0);		}}int main(){	WSAData Wsadata;	int l;	int size;	int error;	int	MaxSocketNumber = -1;	int Senderlen;	int Temp;	string incomingMessage;	SOCKET serverTCP;	SOCKET Client;	sockaddr_in Server;	sockaddr_in Sender;	fd_set socketSet;	char message[256];	WSAStartup(MAKEWORD(2,2), &Wsadata);	serverTCP = socket(AF_INET, SOCK_STREAM, 0);	if (serverTCP==INVALID_SOCKET)	{		printf("Socket Creation Failed");		return 0;	}	else	{		cout<<"Socket Created \n";	}	Server.sin_family=AF_INET;	Server.sin_addr.s_addr=INADDR_ANY;	Server.sin_port=htons(2222);	Temp = bind(serverTCP, (sockaddr *) &Server, sizeof(Server));	if(Temp == SOCKET_ERROR)	{		Temp = WSAGetLastError();		printf("Binding Failed");		WSACleanup();		return 0;	}	else	{		cout<<"Socket Bound \n";	}	listen(serverTCP, SOMAXCONN);	if(Temp == SOCKET_ERROR)	{		Temp = WSAGetLastError();		printf("Binding Failed");		WSACleanup();		return 0;	}	else	{		cout<<"Socket Listening \n";	}	//ADD A UDP SOCKET TO THE MIX		int clientUDP;	sockaddr_in ServerUDP;	int TempUDP;	int UDPSize, UDPClientSize;	char UDPMessage[256];	string messageBuff;	clientUDP = socket(AF_INET,SOCK_DGRAM,0);	if (clientUDP==INVALID_SOCKET)	{		printf("UDP Socket Creation Failed");		return 0;	}	else	{		cout<<"UDP Socket Created \n";	}	ServerUDP.sin_family=AF_INET;	ServerUDP.sin_addr.s_addr=INADDR_ANY;	ServerUDP.sin_port=htons(2224);	int BlockingMode;	BlockingMode = 1;	ioctlsocket(clientUDP,FIONBIO,(u_long FAR*) &BlockingMode);	TempUDP = bind(clientUDP, (sockaddr *) &ServerUDP, sizeof(ServerUDP));	if(TempUDP == SOCKET_ERROR)	{		TempUDP = WSAGetLastError();		printf("Binding Failed");		WSACleanup();		return 0;	}	else	{		cout<<"UDP Socket Bound \n";	}	//END UDP SOCKET CREATION	for (l=0; l<MAX_CLIENTS; l++)	{		ClientEntryList[l].socket_Number = -1;				}	while (true)// continuous loop for the body of the server	{									FD_ZERO(&socketSet);						// Empty the read set		FD_SET(serverTCP, &socketSet);						// Add the Listening Socket		MaxSocketNumber = serverTCP;		UDPClientSize = sizeof(struct sockaddr);																UDPSize = recvfrom(clientUDP, UDPMessage, 200, 0, (struct sockaddr *)&ServerUDP, &UDPClientSize);													if (UDPSize>=0)		{			printf("x");			UDPMessage[UDPSize] = 0;			messageBuff = UDPMessage;			printf("[%s] : %s\n", inet_ntoa(ServerUDP.sin_addr), UDPMessage);		}		else		{			for (l=0; l<MAX_CLIENTS; l++)			{				if (ClientEntryList[l].socket_Number!=-1)				{					FD_SET(ClientEntryList[l].socket_Number, &socketSet);	// add the client to the set of read sockets					if (ClientEntryList[l].socket_Number>MaxSocketNumber)					{						MaxSocketNumber = ClientEntryList[l].socket_Number;//update the max socket number					}				}			}			error = select(MaxSocketNumber+1, &socketSet, 0, 0, 0);// Wait until something happens on any of the connected sockets															if (error<0) 			{				perror("select");					// Error with Select call itself				break;			}					if (FD_ISSET(serverTCP, &socketSet))//a new connection is waiting			{									Senderlen = sizeof(Sender);							Client = accept(serverTCP, (sockaddr *)&Sender, &Senderlen);																								printf("New Client IP Address %s Port %1d\n", inet_ntoa(Sender.sin_addr), ntohs(Sender.sin_port));								for (l=0; l<MAX_CLIENTS; l++)				{					if (ClientEntryList[l].socket_Number==-1)					{						ClientEntryList[l].socket_Number = Client;							memcpy(&ClientEntryList[l].Sender, &Sender,	sizeof(Sender));							break;									}					if (l==MAX_CLIENTS)// Do this if no free client spaces					{											strcpy(message, "There are currently no available slots - Please Try Later\n");						send(Client, message, strlen(message), 0);						closesocket(Client);						}				}				continue;						// Restart While Loop			}			for (l=0; l<MAX_CLIENTS; l++)			{				if (ClientEntryList[l].socket_Number!=-1)				{					if (FD_ISSET(ClientEntryList[l].socket_Number, &socketSet))	// This client!					{							size = recv(ClientEntryList[l].socket_Number, message, 255, 0);						if (size>0)						{					// A message!							ClientEntryList[l].Count ++;							message[size] = 0;							incomingMessage = message;							if(incomingMessage=="INFO")							{								printf("The User has requested INFO");								int i;								for(i=0;i<MAX_CLIENTS;i++)								{									if(ClientEntryList.socket_Number!=-1)									{										char infoMessage[512];										sprintf(infoMessage,"%s\t%d\t%d", inet_ntoa(ClientEntryList.Sender.sin_addr), ntohs(ClientEntryList.Sender.sin_port), /*ntohs*/(ClientEntryList.Count));										send(ClientEntryList[l].socket_Number, infoMessage, strlen(infoMessage), 0);										break;									}								}							}							// Display sender and message//							cout<<ClientEntryList[l].Count<<"\n";							printf("[%s] sends: %s\n", inet_ntoa(ClientEntryList[l].Sender.sin_addr), message);							SendServerMessage(message, ClientEntryList[l]);		// Send to all clients						}						else						{							ClientEntryList[l].socket_Number = -1;		// Client exception error							printf("Client %s has left\n", inet_ntoa(ClientEntryList[l].Sender.sin_addr));							SendServerMessage("Client has Left\n", ClientEntryList[l]);						}						// i.e. Client has left					}				}			}		}	}	for (l=0;l<MAX_CLIENTS; l++)	{		if (ClientEntryList[l].socket_Number!=-1)		{				closesocket(ClientEntryList[l].socket_Number);		}	}	closesocket(serverTCP);		WSACleanup();	return 0;}


And heres the Client:

#include "winsock2.h"#include <iostream>#include <stdio.h>#include <conio.h>#include <string>using namespace std;void main(){	WSAData wsaData;	int remote_port;	char remote_ip[256];	char quitMessage[256];	int statusCode;	if ((statusCode = WSAStartup(MAKEWORD(1,1),&wsaData))!=0)	{		cerr<<"Server failed - error number"<<statusCode<<"."<<endl;		return ;	}	SOCKET tcpClient;	tcpClient = socket (AF_INET,SOCK_STREAM,0);	if(tcpClient==INVALID_SOCKET)	{		printf ("Error at Socket():%ld\n", WSAGetLastError());		WSACleanup();		return ;	}	string selection;		cout<<"Enter UDP if you want to send a UDP message or TCP for TCP\n";	cin>>selection;	if(selection=="UDP")	{		cout<<"You are sending messages via UDP\n";		cout<<"HIT ENTER TO UPDATE MESSAGES\n";		int	UDPSocket;		sockaddr_in server_addr;		int	size;		char	message[256];		int	len;		string UDPBuff;		UDPSocket = socket(AF_INET, SOCK_DGRAM, 0);		server_addr.sin_family = AF_INET;		server_addr.sin_addr.s_addr = inet_addr("127.0.0.1" );		server_addr.sin_port = htons( 2224 );		while (1) 		{			cin>>UDPBuff;			if (fgets(message, 255, stdin)==0)			{									// Get input from keyboard				break;			}									// Exit While loop when EOF marker found			message[strlen(message)-1] = 0;			UDPBuff = message;			sendto(UDPSocket, message, strlen(message), 0,(sockaddr *)&server_addr, sizeof(server_addr));		}							// Repeat forever		closesocket(UDPSocket);		WSACleanup();		return;		}	if(selection=="TCP")	{		cout<<"Enter the IP you wish to connect to: ";		cin>>remote_ip;		remote_ip[strlen(remote_ip)-1] = 0;		cout<<"\nEnter the Port Number you wish to connect on:";		cin>>remote_port;		cout<<"\nAttempting to connect to "<<remote_ip<<" : "<<remote_port<<"\n";		sockaddr_in clientService;			clientService.sin_family = AF_INET;		clientService.sin_addr.s_addr = inet_addr("127.0.0.1" );		clientService.sin_port = htons( 2222 );		if ( connect( tcpClient, (SOCKADDR*) &clientService, sizeof(clientService) ) == SOCKET_ERROR)		{			printf( "Failed to connect.\n" );			WSACleanup();			return ;		}		char buffer[256];		int Temp;		char incoming[512];		int iTemp;		FD_SET read;		string output;		FD_ZERO(&read);		FD_SET(tcpClient, &read);		cout<<"PRESS RETURN TO UPDATE MESSAGES\n";		while(1)		{			cin>>output;				if (fgets(buffer, 255,stdin)==0)			{				break;			}			buffer[strlen(buffer)-1]=0;			if(output=="AUTH")			{				cout<<"You are now connected to the Server\n";				while(1)				{					if (fgets(buffer, 255,stdin)==0)					{						break;					}					buffer[strlen(buffer)-1]=0;					output = buffer;								if(output=="QUIT")					{						cout<<"You Have Closed The Client Socket\n";						closesocket(tcpClient);						WSACleanup();						return;					}					if(output=="INFO")					{						cout<<"You Have requested the User Info from the Server\n";					}						Temp = send(tcpClient, buffer, strlen (buffer),0);					iTemp = recv(tcpClient, incoming, 256 , 0);					if(iTemp>0)					{						incoming[iTemp] = 0;						printf("[%s] sends %s\n",inet_ntoa(clientService.sin_addr), incoming);					}				}			}			else			{				cout<<"Thats the incorrect command please close and try again\n";				closesocket(tcpClient);				WSACleanup();				return;			}		}				}cout<<"You have chosen to shutdown the client\n";		closesocket(tcpClient);WSACleanup();return ;}


Well there you have it - basically i just want to send a message from the client to the server, completely useless i know but for now thats the step that i want to take. I can move on from there.

Cheers for any suggestions
Neil

P.S - If i make the UDP socket blocking again it will recognise that something has been sent, but then won't let me do any of the TCP stuff.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.