Asynchronous Sockets and opengl

Started by
6 comments, last by Grecco 16 years, 1 month ago
I am working on taking a simple opengl game and converting it to multi player using a client server approach. So far, i have created a simple client/server console program using blocking ports and as far as i understand, I need to be using asynchronous sockets under win32 application. I am completely new to using windows programming, should i attempt to upgrade my current console program to a win32 program, then import the opengl code? thanks!
Advertisement
There is no need to use asynchronous sockets just because you are in windows.

Especially since the software is already using OpenGL, you may have chosen it for cross-system compatibility.

Though i personally feel it's more handy to use asynchronous.
But that's just me, i use DirectX couldnt care less about the linux users ;)
what alternate connection strategy do you recommend? just blocking sockets for both server and/or players, or some method of using threads for each player, or something else completely perhaps?

I only asked about asynchronous sockets due to reading lots of articles about them

the game is a 3+ player opengl racing game where the players info and position will be sent to a server, and server will send it out to the other players.
Opengl and C must be used, but type of sockets or method of connecting the players to the server is optional.

I guess there is a lot of information on how to do each method, but im not sure which is best method for my situation.


EDIT: oo! i guess i should read the forum FAQ

After reading the FAQ, It recommends i should:
use UDP,
use Non-Blocking sockets with Select "easiest to implement correctly, but will also perform well" <- music to my ears:)

I thought asynchronous sockets were the same as non-blocking... guess not..

Should i leave the server with blocking sockets? or change them to non-blocking as well?

[Edited by - odi3 on February 18, 2008 9:34:08 PM]
Personally I've had no trouble with blocking sockets if select() is used appropriately. The amount of code you need to change to go from one to the other is minimal anyway, so don't worry about it too much.
isnt select used for non-blocking and async sockets?
For client, you can use blocking socket in a thread, or non-blocking socket in main thread.

Don't run blocking socket in main thread through - one network hick-up, and your application will stall.

Async sockets are Windows specific (generally bad choice) - async networking is something different (IOCP under Windows or AIO under Linux). If you need high-throughput, such as on busy servers, then async networking is a good choice, but non-blocking sockets work for that as well.
Ok, Ive tried to set up a blocking server with blocking sockets to get an idea of how to do all this stuff.

At one point i had it working with a small bug, in an attempt to change the client, i screwed it up and cant figure out where i screwed it up...
I guess im just burnt out from looking at it...

Anyone have any ideas where i went wrong?
#include <string.h>#include <winsock2.h>#include <stdio.h>#define WIN32_LEAN_AND_MEAN#pragma comment( lib, "WS2_32.lib" )     // This will link to wsock32.lib// WinSock globalsSOCKET s;			// Socket handlestruct sockaddr_in you;	// Server's attributesstruct sockaddr_in target;	// Client's attributesint debug = 1;const int MAX_PLAYERS = 2;struct Car {	double positionX;	double positionY;	double positionZ;	double velocityX;	double velocityY;	double velocityZ;	double orientationX;	double orientationY;	double orientationZ;};struct Car cars[2];//MAX_PLAYERS];int myPlayerID;char buffer[BUFSIZ] = "";    // text buffer WSADATA w;int error;char a;int i;int byteCount;void myReceive(){		byteCount = recv (s,buffer,strlen(buffer),0);	sscanf(buffer, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf ", 		&cars[0].positionX, &cars[0].positionY, &cars[0].positionZ, 		&cars[0].velocityX, &cars[0].velocityY, &cars[0].velocityZ, 		&cars[0].orientationX, &cars[0].orientationY, &cars[0].orientationZ,																	&cars[1].positionX, &cars[1].positionY, &cars[1].positionZ, 		&cars[1].velocityX, &cars[1].velocityY, &cars[1].velocityZ, 		&cars[1].orientationX, &cars[1].orientationY, &cars[1].orientationZ);		if (debug == 1)	printf("BUFFER = %s\n", buffer);	printf("Doubles Received from Server: %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf \n", 		cars[0].positionX, cars[0].positionY, cars[0].positionZ, 		cars[0].velocityX, cars[0].velocityY, cars[0].velocityZ, 		cars[0].orientationX, cars[0].orientationY, cars[0].orientationZ,		cars[1].positionX, cars[1].positionY, cars[1].positionZ, 		cars[1].velocityX, cars[1].velocityY, cars[1].velocityZ, 		cars[1].orientationX, cars[1].orientationY, cars[1].orientationZ);}void mySend(struct Car myCar){	sprintf (buffer, "%lf %lf %lf %lf %lf %lf %lf %lf %lf ", 		myCar.positionX, myCar.positionY, myCar.positionZ, 		myCar.velocityX, myCar.velocityY, myCar.velocityZ, 		myCar.orientationX, myCar.orientationY, myCar.orientationZ);		if (debug == 1)	printf ("BUFFER= %s\n", buffer);	printf ("Sending to Server: %lf %lf %lf %lf %lf %lf %lf %lf %lf \n", 		myCar.positionX, myCar.positionY, myCar.positionZ, 		myCar.velocityX, myCar.velocityY, myCar.velocityZ, 		myCar.orientationX, myCar.orientationY, myCar.orientationZ);		byteCount = send (s, buffer, strlen(buffer)+1, 0);} int myConnect(char ip[9]){	printf ("Client Started\n");// Setup WinSock	error = WSAStartup (0x0202,&w);	if (error)	{		printf ("Error: Problem while verifying Winsock Version\n");		return -1;	}	if (w.wVersion!=0x0202)	{		printf ("Error: Wrong WinSock version\n");		closesocket(s);		WSACleanup ();		return -1;	}//	s = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); // UDP NOT WORKING YET	s = socket (AF_INET, SOCK_STREAM, 0);          // TCP	// end Game_Init	target.sin_family = AF_INET; //address family Internet	target.sin_port = htons (5555); // set server's port number	target.sin_addr.s_addr = inet_addr (ip); //set server's IP (currently using loop back)	if (connect(s, (LPSOCKADDR)&target, sizeof(target))== SOCKET_ERROR)	{		// an error connecting has occured!		printf ("SOCKET ERROR\n");		closesocket(s);		WSACleanup ();		return -1;	}	//		receive player number	byteCount = recv(s,buffer, strlen(buffer),0);	myPlayerID = buffer[0] - '0';	printf ("I am Player %d\n", myPlayerID);	return myPlayerID;}int main ( void ){	int y = 0;	SOCKET s;			// Socket handlestruct sockaddr_in you;	// Server's attributesstruct sockaddr_in target;	// Client's attributes	error = myConnect("127.0.0.1");	if (error < 0){		printf ("Error: Problem connecting to server\n");		return 1;	}	cars[myPlayerID].positionX = 0;	cars[myPlayerID].positionY = 0;	cars[myPlayerID].positionZ = 0;	cars[myPlayerID].velocityX = 0;	cars[myPlayerID].velocityY = 0;	cars[myPlayerID].velocityZ = 0;	cars[myPlayerID].orientationX = 0;	cars[myPlayerID].orientationY = 0;	cars[myPlayerID].orientationZ = 0;	for(;;){	cars[myPlayerID].positionX++;	cars[myPlayerID].positionY++;	cars[myPlayerID].positionZ++;	cars[myPlayerID].velocityX++;	cars[myPlayerID].velocityY++;	cars[myPlayerID].velocityZ++;	cars[myPlayerID].orientationX++;	cars[myPlayerID].orientationY++;	cars[myPlayerID].orientationZ++;	mySend(cars[myPlayerID]);	myReceive();	}		printf ("Client Quiting\n");	closesocket(s);	WSACleanup ();return 0;}////////////////// server#include <string.h>#include <winsock2.h>#include <stdio.h>#pragma comment( lib, "WS2_32.lib" )     // This will link to wsock32.lib#define WIN32_LEAN_AND_MEANconst int MAX_PLAYERS = 2;//Winsock globals	SOCKET s[2]; 	SOCKET listeningSocket;	struct sockaddr_in me;	struct sockaddr you[2];	WSADATA w; // get winsock version	int debug = 1;	int byteCount;	struct Car {	double positionX;	double positionY;	double positionZ;	double velocityX;	double velocityY;	double velocityZ;	double orientationX;	double orientationY;	double orientationZ;};struct Car cars[2];void mySend(SOCKET s){	int i = 0;	char bufferTemp[1024] = "";	char bufferTemp2[1024] = "";	for(i = 0; i < MAX_PLAYERS;i++){		sprintf (bufferTemp2, "%lf %lf %lf %lf %lf %lf %lf %lf %lf ", 				cars.positionX, cars.positionY, cars.positionZ, 				cars.velocityX, cars.velocityY, cars.velocityZ, 				cars.orientationX, cars.orientationY, cars.orientationZ);		strcat(bufferTemp, bufferTemp2);	} 	byteCount = send (s, bufferTemp, strlen(bufferTemp)+1, 0);	if (debug == 1)	printf("BUFFER = %s\n", bufferTemp);	printf("Doubles sent to both players: %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf \n\n",				cars[0].positionX, cars[0].positionY, cars[0].positionZ, 				cars[0].velocityX, cars[0].velocityY, cars[0].velocityZ, 				cars[0].orientationX, cars[0].orientationY, cars[0].orientationZ,																			cars[1].positionX, cars[1].positionY, cars[1].positionZ, 				cars[1].velocityX, cars[1].velocityY, cars[1].velocityZ, 				cars[1].orientationX, cars[1].orientationY, cars[1].orientationZ);}// update structure with values from buffervoid myReceive(int playerID, SOCKET s, char buffer[1024]){			int error = recv (s, buffer, sizeof(buffer),0); // tcp					if (buffer[0]=='!')			{				printf("Player %d quit! EXITED\n", playerID);				printf("Server Quitting...\n");				WSACleanup ();				exit(1);			}			if (error==INVALID_SOCKET)			{				printf("Error:  Player %d quit! INVALID SOCKET\n", playerID);				printf("Server Quitting\n");				WSACleanup ();				exit(1);			}	sscanf(buffer, "%lf %lf %lf %lf %lf %lf %lf %lf %lf ", &cars[playerID].positionX, &cars[playerID].positionY, &cars[playerID].positionZ, 												&cars[playerID].velocityX, &cars[playerID].velocityY, &cars[playerID].velocityZ, 												&cars[playerID].orientationX, &cars[playerID].orientationY, &cars[playerID].orientationZ);	if (debug == 1)	printf("BUFFER = %s\n", buffer);	printf("DOUBLES Received from player %d %lf %lf %lf %lf %lf %lf %lf %lf %lf \n", playerID, cars[playerID].positionX, cars[playerID].positionY, cars[playerID].positionZ, 												cars[playerID].velocityX, cars[playerID].velocityY, cars[playerID].velocityZ, 												cars[playerID].orientationX, cars[playerID].orientationY, cars[playerID].orientationZ);}int main ( void ){	int addr_size = sizeof(struct sockaddr);	char buffer[1024] = "";	int playerID = 0;	int error;	printf("Server Started\n");	error = WSAStartup (0x0202,&w);  	if (error)	{		printf("Error: Problem while verifying Winsock Version");		return 1;	}	if (w.wVersion!=0x0202)// check if winsock is version 2.02	{		printf("Error:  Wrong WinSock version!\n");		WSACleanup ();		return 1;	}	listeningSocket = socket (AF_INET,SOCK_STREAM, IPPROTO_TCP);          // TCP	me.sin_family = AF_INET;	me.sin_port = htons (5555);	me.sin_addr.s_addr = htonl (INADDR_ANY);	if (bind(listeningSocket,(LPSOCKADDR)&me,sizeof(me))==SOCKET_ERROR)	{		printf("Error:  Unable to bind socket!\n");		WSACleanup ();		return 1;	}	if (listen(listeningSocket, MAX_PLAYERS)==SOCKET_ERROR)	{		printf("Error:  Unable to listen!\n");		printf("%s \n", WSAGetLastError());		WSACleanup ();		return 1;	}	printf("Listening for connections...\n");	while (playerID < MAX_PLAYERS)	{		s[playerID] = accept (listeningSocket,&you[playerID], &addr_size);		if (s[playerID]==INVALID_SOCKET)		{			printf("Error:  Unable to accept connection!\n");			WSACleanup ();			return 1;		}		else		{			printf("Player %d joined!\n", playerID);						// send player his player number			sprintf (buffer, "%d", playerID);			byteCount = send(s[playerID], buffer, strlen(buffer)+1, 0);					playerID++;		}	}	printf("Starting Game!\n");		while (1)	{		playerID = 0;		do		{						myReceive(playerID, s[playerID], buffer);						playerID++;					}while (playerID < MAX_PLAYERS);		mySend(s[0]);		mySend(s[1]);	getch();	}	}

After i get this working, im hoping to dabble figuring out how udp and or nonblocking works to apply to a game.. Is it a lot of work to convert?

*added source tags - Gaiiden

[Edited by - odi3 on March 18, 2008 12:18:25 AM]
Have a look at the asynchronous I/O library: http://asio.sourceforge.net. It has a beautiful model for handling asynchronous communication and will allow to rapidly construct a prototype.
Simulation & Visualization Software
GPU Computing
www.organicvectory.com

This topic is closed to new replies.

Advertisement