Winsock Programming Assistance Needed

I am trying to figure out how to do a multiplayer server in Winsock. I need help with connections and data management. I want to know how I can let multiple clients connect to the server and send data to the server (example: movement, login, etc.) and the server be able to determine who is sending the data and then send the data to all clients other than the client who sent it. I am fairly new to Winsock but I am wiling to listen to people and learn. I have it where a client can connect and the server knows it is, but I am not sure how to go about the above, if I even need to change much.

Here is an example of what I would want to happen: Player 1 tries to connect to the server. The server accepts the connection. Player 1 sends the server their login details. The server checks the login details and sends player 1 a confirmation weather the login was successful or not. Lets say it was, then player 2 connects and same as player 1 happens, except this time when player 2 connects player 1 is notified. Then say player 1 moves 1 to the right, player 1 sends some data to the server the server then sends the data to all players other than player 1, in this case just to player 2. Then when one of them disconnects the other is notified.

That is a basic overview of what I would want. I assume the easiest way to handle the data is to have a header sorta speak sent with the message that is sent before the rest of the data, but how I would implement that I don't know.

I am using Game Maker (http://yoyogames.com/) to make the client. I am going to be using either this: http://gmc.yoyogames.com/index.php?showtopic=90437 or http://gmc.yoyogames.com/index.php?showtopic=509556 on the client side to handle sockets.

Thanks,
legobear154
Here is the full description for winsock programming and sample project cyber management source code.
http://codeincodeblock.blogspot.com/2011/10/winsock-programming-sample-project.html
You allow multiple clients to connect to a single host by assigning each connection it's own thread. This method will allow you to identify the clients in any number of ways from the threadID, to the users login name, their IP address or whatever method you are comfortable with. As for how the server knows when to send data to all players and when to send it to only one, I would use a global struct to manage this, that way it will be accessable to all of the threads at once.
So basically, I could accept the connection and it be assigned to a variable I can set in some way. Or would I create multiple sockets using socket() and assign it to the variable of my choosing, probably the persons username, and bind it? If I do it by username, how would I go about getting their username? Would I send it when the client tries to connect? or after the server accepts the connection?

The players login info would be stored in a mysql database so the user can log into my site and see possibly stats, leaderboards, etc. Is this easily achievable? Is there a good library for handling mysql database connections and queries?

Also, I am going to be creating multiple games that would allow multiplayer. The way I was thinking about setting it up was have a main server handle all the logins for all my games. Then once the player has logged in the server determines what game they are playing and sends the client a list of all available servers for the game, the list would consist of the name of the servers, the IP of the servers, how many users are on the severs, and possibly the owner of the servers. The clients would then do the connection the the multiplayer server of their choosing, or through a matchmaking style lobby. If it is through a matchmaking style lobby then the client would ping each server determining which is better. The lists would be saves to a mysql database so my site could access it easily and display it. Would this be effective? Is there an easier way?
Could I have an infinite amount of people connected to the main server without much lag?
Would it be easier/ more effective to just connect to the main server to login, logout, and when you want to refresh the server list? I figure the last one would be better, but I would have to probably find a way to manage all the data entering and exiting the server so it doesn't get swamped with requests and connections.
Would a distributed load server of some form work?

Could you show me a basic global struct that could be used? They don't make very much sense to me at times. Or could you link to a site that describes them well?

Again, I am new to winsock programming, so if I am miss understanding something I am sorry and please correct me.

Thanks,
Legobear154

Also, @ Dinesh subedi: I am looking through the site and looking through the source code given on the site.

Also, sorry about all the questions, I just want to learn :p
In the Win32 API send() and connect() are two completly seperate functions, so your question about when to send the user data is answered for you. Once a connection is established between the server and the client you enter a loop that constantly sends and recieves data between the two, I would personally send the username right before entering this loop. Again, each connection to the server should be managed by it's own thread so you will not have to keep sending the username.

I can't comment on the MySQL library, I've downloaded and glanced at it but I haven't had a reason to personally use it.

As for the multiple games on one server bit, consider using VM's. One set of hardware and as many virtual machines as you want. This should simplify the issue for you. The rest of that paragraph seems to be you getting ahead of yourself.

When I said global struct I mean a custom structure that is avalible in the global memory space. I can't show you an example without knowing what data you are trying to pass back and forth, then we get into compression and blah blah blah...
So, once the connection is established between the server and client and the server accepts it send the username? Then go into a loop on the client? How would I go about assigning the thread to the username?

The way I am thinking about doing the multiplayer games is having it where there is no dedicated servers, other than the main server I am trying to figure out right now. The players playing the game would be hosts, but that is something different that I do not need to talk about here as it doesn't pertain to C++ exactly, unless I am going to write my own dll to do it.

I don't have a computer I can set up as a dedicated host at this moment, I figure once I get the programming out of the way more I can worry about the hardware and VM's.

All I really want the main server to a gateway to the other servers and to handle a few things for my site, like updating user status on it. Which is what the MySQL library would be for.

Right now though I only have one game I am working on that will have multiplayer, so as far as I am concerned a single server will work for the moment. I just want to be ready for anything else I may have to add to it, or modify later.

As for the data I would send back and forth it would be login details and a server list of some sort that would list the IP of the server, name of the server, the number of players currently connected, and maybe the owner of the server. Possibly in an array? Although I don't know how the client would read it since the client wont be in C++.

I tend to get ahead of myself a lot, but I have good intentions :)

I am going to try and take this one step at a time and not get ahead of myself.

Thanks,
Legobear154
Then go into a loop on the client?

Both the client and the server would enter a message loop after they connect. The loops exist in their own threads leaving your application free to accept more incoming connections.

How would I go about assigning the thread to the username?

When the connection is made, when your Server side app progresses past the listen(...) function and before you even get to accept(...), you launch a new thread to manage everything about that connection. Alternativley you could launch each listen(...) function as it's own thread but the vital part is that each connection has it's own message and control loop on your Server app. Since the data for each thread will be unique to each instance you don't need to worry about assigning the thread to the username, it will could be stored as a local variable if that's how you wanted to do it.

All I really want the main server to a gateway to the other servers and to handle a few things for my site, like updating user status on it.

Then the "other servers" as you put it will need to establish a connection with your Main Server probably via the same way. They would then send you any information you say is relavent for the clients to establish a connection to them.

Although I don't know how the client would read it since the client wont be in C++.

The language it's written in won't matter... Data is data. The client would recieve this data from your Main Server the same way that it recieves data from the Other Servers. You then cast that data into the correct format and render it on screen.
Last edited on
Just to make sure I am understanding this. So I would, of course, start a listening socket and bind it and everything just like normal. I would listen on that socket and wait for a connection. Once I get a connection from a client I move the connection to its own thread on the server. How would I go about moving it to its own thread? That thread would go into a loop listening for incoming messages using a while loop probably. As new connections are made new threads are created each time. When a connection is dropped/ disconnected the thread ends. Each thread will only handle the data for their particular connection. Am I understanding correctly?

How do I go about creating threads? What would be a good way to do it efficiently? I found this when searching for multi-threading in c++ http://www.devarticles.com/c/a/Cplusplus/Multithreading-in-C/ I am reading through it as we speak, maybe I will get some idea of a good way to do it.

I figure the best way to handle the other servers is for them to connect to the main server on a completely separate port from the clients and have them all running in separate threads like the clients.
Or, maybe a better way to do it could be for the other servers to connect to the main server to give some basic data, IP and name would be all, that is stored on the database when the other server first comes online, then disconnects from the main server after the data is send and is confirmed that it was added to the database. When a client connects to the main sever and asks for a server list the main server send the client the IP and name of the servers. Then the client tries to connect to the other servers and if they are full tell the client, otherwise connect. Then when a server shuts down, tell the main sever and have it remove the servers data from the database before it shuts down completely.

The "other servers" would be for the client to connect to so they can actually play online with other players. Think of it as matchmaking like in Halo or Call of Duty, or really any other multiplayer game on Xbox Live.

Would it be a good idea to disconnect the client from the main server once the server list is sent to save bandwidth? The connect only when to log out or to update the server list?

Thanks,
Legobear154

I appreciate all the help!
My posted program is my college mini project written in C and compile in codeblocks.In this program we use file system to store the username and password.We can create new account in server for client.
In this program when client connect ot the server their seprate thread creates and we can exchange message between them.
I think you want to make game and store data in mysql then I refer you to write program in Visual studio using visual C++ so you can easily acess the sql server to store data.You can also easily manage memory.Go to microsoft site http://msdn.microsoft.com/en-us/library/windows/desktop/ms738545(v=vs.85).aspx you get all meterial from these site.
Thank you, but I have tried Visual Studio and every time I install it, it causes my laptop to freeze up and the program crashes. I prefer to use just plain old C++. Part of the reason I want to is so I can possibly port it to other Operating Systems in the future. Also because I know C++ more then any other programming language out there and I would prefer to stick with what I know. I don't really want to have to learn the Visual C++ specific things because I do, in the future, want to make cross-os compatible programs, and I feel that learning Visual C++ could make it harder in the end to do such. This is just my personal preference and I hope I haven't offended anyone.

Anyway, could someone explain this in a better way to me than this site: http://www.devarticles.com/c/a/Cplusplus/Multithreading-in-C/1/

HANDLE CreateThread(LPSECURITY_ATTRIBUTES secAttr,
SIZE_T stackSize,
LPTHREAD_START_ROUTINE threadFunc,
LPVOID param,
DWORD flags,
LPDWORD threadID);

What are all the parameters exactly? I don't quite understand the site I found it on. I know secAttr is the security descriptor and that NULL is default. I also know stackSize is basically the size of the thread and that if it is set to 0 then it will expand if it needs to. As for the rest, I am not sure about.
well... stackSize...
How would I go about creating a new thread when a new connection is created?

Thank you,
Legobear154
Here's a better link: http://msdn.microsoft.com/en-us/library/ms682453(VS.85).aspx
The parameters are a little intimidating to look at but they aren't complicated once you learn them.

- LPSECURITY_ATTRIBUTES: This is a pointer to a structure unique to Win32 that holds information regarding a users Security information. This is useful if you want to impersonate another user while running this function otherwise setting it to NULL will tell the function to use the default SECURITY_ATTRIBUTES structure.

- SIZE_T: Each thread has it's own unique memory allocation area called a stack. This parameter will let you set a customized size for this stack upon creation of your thread. Setting this argument to 0 tells it to use the default setting this is what I recommend doing.

- LPTHREAD_START_ROUTINE: This is whre the magic starts. This is a pointer to the function that you want to use as the start of your thread. Regardless of the return value of your function you must cast it to a LPTHREAD_START_ROUTINE datatype. You only need to place the name of your function here. NOTE: If this function excepts arguments they must be in the form of a void* or LPVOID.

- LPVOID: This is the argument you may pass to your function. Like I mentioned above it has to be a void* but you can cast it to what ever you want inside of your function so that doesn't matter so much. If your function does not take arguments then this can be NULL.

- DWORD: This is the creation flag. Check the link I gave you above for more detail on this one, generally you'll want it to be 0 so that your thread starts right after it's created, this is what I recommend doing.

- LPDWORD: A pointer to a DWORD that will hold the ThreadID number. This can be NULL if you don't care about the new threads ID number.
Last edited on
Ok, so, I would create a function that has a loop in it and then use that function inside the CreateThread function, like so: CreateThread(NULL,0,client,NULL,0,NULL);

client being a function I create that has a loop in it.

How would the loop that runs in the new thread know what socket to receive data from? Would I have to pass it as an argument then go from there?

Thanks,
legobear154
Yup, the socket would be passed as an argument to the function. At least that's how I would go about doing it.
How would I pass the socket to it exactly? I mean obviously it would be something like: CreateThread(NULL,0,client,socket,0,NULL); I found an example, I don't remember where and I'm not on the computer I bookmarked it on, that, from what I could tell, started a listening socket and waited for a connection. When a connection cam along it accepted it and passed it to a function that CreateThread ran. It was after the connection was accepted. I am looking for it right now...
Last edited on
You have to cast the SOCKET variable to an LPVOID, then back to SOCKET inside of the function and use it in the running loop like you normally would.
Topic archived. No new replies allowed.