Sign in to follow this  
odi3

Asynchronous Sockets and opengl

Recommended Posts

odi3    122
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!

Share this post


Link to post
Share on other sites
marius1930    119
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 ;)

Share this post


Link to post
Share on other sites
odi3    122
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]

Share this post


Link to post
Share on other sites
Kylotan    10010
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.

Share this post


Link to post
Share on other sites
Antheus    2409
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.

Share this post


Link to post
Share on other sites
odi3    122
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 globals


SOCKET s; // Socket handle
struct sockaddr_in you; // Server's attributes
struct sockaddr_in target; // Client's attributes

int 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 handle
struct sockaddr_in you; // Server's attributes
struct 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_MEAN

const 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[i].positionX, cars[i].positionY, cars[i].positionZ,
cars[i].velocityX, cars[i].velocityY, cars[i].velocityZ,
cars[i].orientationX, cars[i].orientationY, cars[i].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 buffer
void 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]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this