![]() |
| ||
| Winsock Multi-Client Servers (This document is dedicated to my friend Aaron Anderson) (Fog Edition means I dont tell you everything stright.All the info will be there but you will have to do much thinking) Servers and Clients,the backbone of the internet after the TCP/IP protocol.Right now I will go yak yak on TCP/IP so if you know it skip this.Also I intend not to provide you with everything. I will provide enought material and directions for you but you will have to do something on your own.I just teach you how to setup a basic server which can accept multiple connection and of course guidlines on how to make a robust server.We will also look into a very simple kind of server 'Chat servers'. TCP/IP ------- TCP stands for Transmission Control Protocol.IP stands for Internet Protocol Address.TCP implementations provides a defined way about how data transmissions can be done over the wire between diffrent computers.There are a few sub protocols but we wont worry about them since they are at a lower level. OSI Model ---------- It is an open standard published by the ISO(International Standards Organisation) on how systems can recive and transmit data with each other.TCP/IP is an implemetation of it. It has 7 layers and each do a diffrent job.We dont want to go into details now. This helps various computer with diffrent hardware and OS to communicate with each other without any special work and diffrent OS can transfer data transperantly.This enable a network to consit of diffrent machines and still transfer data without a problem http://www.webopedia.com/quick_ref/OSI_Layers.asp How TCP works --------------- A basic overview of course.When a client wants to connect to a server it send an SYN packet to the server.The server responds with a SYN/ACK packet to which the client responds with a ACK packet. Client ---> SYN ---> ServerThis is called a 3 way TCP/IP hand shake.Then the connection is ready for transmitting data. The data sent is broken up into multiple packets and sent between the client and server.There are mechanisims to ensure that the packets are recived and assembled in the correct order and the data has not been corrupted.If it has been corrupted the data has to be retransmitted. Along with a lot more protections, error checks etc etc .... We never see any of this as they are handled at lower levels so we dont need to worry about them. Ports ----- The ships dock here.Actually ports are a way to seperate diffrent connections.When a client connects to a server there mabe more than one service running on that machine or if the data is sent to the client how,does one say which app gets that data.Ports range from 0-6255.They serve to identification which service a client wants to access or which client app should get the info. Now you got a very basic intro on how computers communicate we can go about designing servers. I will provide a basic client here with will be used for testing.We will not disscuss it much. /*-------------------Echo_client.cpp-------------------*/ Server Mania ------------- There is a curse which goes "May you live in interesting times" and making servers will only help it. Planning is as improtant here as it is else where.I will give a few basics by which you should be able to plan and build your own servers with multiple client support. We will build a single thread server with support for multiple clients.All info about a client will be kept in a structure and funtions will use that info to perform various jobs. Client Sturcture: struct _clientThe obvious funtions we need are: accept(_client *); //accept client connectionsGlobals: MAX_CONS //Total No of Client allowedWe will build a version of an echo server.Any data sent by any client is sent to all the clients connected. Chat server work in a similar manner.We will be doing a bare bones server and wont put in too much error checking. Basic Server Skeleton --------------------- This describes how a server is structured. 1.Initialise a few variables i.e. the port,ip etc of the server 2.Start Winsock.(A must for windows server and clients) 3.Create the Socket 4.Set the Socket options 5.Bind the server to a port 6.Set Listen Mode 7.Set non-blocking mode.(Important if your server supports multiple clients or is gui) 8.Start the server loop 9.Exit server loop and cleaup memory 10.Stop Winsock. Note:Of course most parts have their own error checks. Now the server is not very much diffrent from the client see below for steps 1 to 7. /****************SERVER.cpp****************/Notes ------ 1.htons() This funtions is used make port numbers correct according the hardware.This is due to the fact the diffrent hardware store numbers diffrently.If this is not called clients from other computers will not be able to establish a connection. 2.bind() - binds the server to a specified port 3.listen() This is used to set the listen mode and set the max amount of packets that will be allowed to be stored at a time.If the no of packets exceed the limit they will be conveniently dropped. 4.ioctlsocket(); Set the blocking mode.Set b to one to make the socket a non-blocking one.In non blocking mode the funtions will return immediately even if they have not got any respone.This will prevent them from stopping the program operation till they get a response.This will enable us to loop through all the clients and respond to the ones who have sent commands.Eg.In blocking mode the accept() will wait till it recives a connection before it returns and in non-blocking mode it returns immediately. Server Loop ------------ This is where all the work of a server is done while(true)That's it basically.Of course the the 3 funtions will be very similar to a simple server but they will also have to handle some more work. Low Level funtions ------------------ In a simple server we used funtions accept(),send(),recv() to interact with the client. We will now overload them to do our work. Accept funtion --------------- int accept(_client *x)Notes ------ x->cs = accept(sock,(sockaddr *)&x->addr, &x->i) is quite note worthy.Here we assign the return of the funtion to another SOCKET(x->cs) variable. We will be using this variable to communicate with the client.'sock' will be used only for accepting connections. (x->addr) will have all client related info like the IP address. The rest is simple.If the return is valid then set the connection status (i.e x->con) to true and initialise the fd_set.This will be used to check if data is present in the socket. Send Funtion ------------- int send(_client *x,char *buffer,int sz)Notes x->i is used just because it's avilable,use another one if you like. If there is a socket error or the return is 0 disconnect.I recomment you find some out.We will be making disconnect() later.Zero means the client has disconnecter.-1 i.e socket error means the client is unreachable due to any reason. Recv Function -------------- int recv(_client *x,char *buffer,int sz)That's it you have all the basic structre and low level stuff you need to build a simple server. Now we are free to tackle building a robust server. Building Robust Servers ---------------------- Bang,Crash,Hi,Hello,Crack,Oh master,ha,Woof............... sounds weird.Well they repesent how diffrent client connect and how they behave.Some leave by saying good bye others leave the line open,other disappear etc etc. So one of the most important things for any server would be to keep track of client connections. Connections appear and disappear at random so it best to have some central command to keep track of server status and various connection details.The major problem will be clients disappearing if we are not implementing a lot of checks( like now). We will be relying on the send funtion mainly to see if a client has left us or is unreachble.That means recv() will not show any error unless a client has quit properly but send will pick up a missing client.This is not much of a problem since you will almost always have to send data to client continously.If no activity( i.e sending) then a improperly disconnected client will remain in the memory and will not noticed untill you send it some data.This should not pose any probs anyways so no need to worry about this. Its best to have a server as modular as possible to enable modifiactions (which will be extensive) without breaking any code.That would make things like porting(ie getting it to work on other OSs) upgrading etc easy. Oh yes there are always memory, it's alway limited, even if you are in a sea of memory,llike the old saying goes "water,water everywhere not drop to drink".Other problems include things like buffer overflows and illegal memory access.Brr goes crazy very quickly if your server has even 1 leak. Now these are the few common problems.There are more when you go to make your server more funtional.Following a few guidelines will sure help reduce them.(Noodles but you cant have it anyother way) 1.If random memory access is used always provide for errors and deallocate memory on crashing 2.As far as possible never hard code anything. 3.Use defines when values have to be hard coded 4.Modularity is a must.Keep funtional code seperate from network code 5.Memory should always be conserved. 6.If linked lists are used, use a manager class to use them through,never directly 7.Seperate your code into diffrent segments and keep them in diffrent headers 8.Always develop funtions to check the status and look for errors on your server including but not limited to no. of clients, memory usage, client details etc. 9.Try for max performance even if you are on a supercomputer. This should be enough for a start.I will only discuss a few of them.The others you have to figure out. Modularity ---------- Oh,well you should know it so I will just brush on it.Why you still need it?Security Yes,that wonderful oxcymoron.If all your send and recive are channeled through one place it will be eaiser to implemet restrictions and permmisions.So reduce the number of places you call recv(sock... or send(sock... to one place and use higher level funtions to call them.Try to limit the network code as much as possible.Also seperate the recive, send, and accept funtions.This will enable you to go multi-thread without trearing anything. Status and Error Monitering --------------------------- Develop these early.They will be a great help for debuging your code. Well below you will see what a status monitor looks like.You can build diffrent ones if you like or even integrate it with the lower level funtions.It's better if all this goes to a central location as you will always be informed. Of course not just one funtion can do all the work.You will have to develop ones which will have to look at each connection as report details like the IP address etc.Also debug funtions. [Maybe more,but in a biginner tut it wont be of much use] Back to coding ---- > The server loop is given below.You will have to develop the funtions on your own.Hey do say this is a tut and all has to be told.I did tell everything.I gave you funtions to handle send, recive and accept through the client structure dint I.All you have to do now is make a glorified loop. while(true)I wont leave you hanging up on a tree though _client client[MAX_CONS];That's it,now you have enough stuff to setup a server that will accept multiple connections. Chat Servers ------------- Chat servers are the easy to build since they have little work to do and require no protocol. The code I gave above is sufficent to build a simple one.You will just have to build recv_clients() and a chat_message(char *s). Now let look at what a basic chat server does.Well a client connect,nick names himself,and the types messages which are transmitted to everyone.I wont show how to handle the nick registration (you do that) but I will show you a way to respond to a command and a simple chat message. Let's say all our commads start with a / and they will be handled server side.Ok get hold of the server code I already gave and put in the server loop.You will have to define the messages,MAX_CONS and PR_CONS.(also remove the send_client() will will not need that here). Thse chat_message funtion just has to send a text message to all connected clients. void chat_message(char *s)Now the recive funtion has to get a message from any client who sends a message #define BF_SZ 100Naturally,Now you have a chat server,but you cant say who said what.For that you will have to add a char variable to the _client struct respond to a command to assign the nick.Then add the nick to the beginig of every message and voila a better chat server.More polish would invlove alerting all the clients when a fellow connects or disconnects.(Server_Stats() can do that).No need for me to do that it's simple and you will get more satisfaction if you do it.Else it will be no more than copy paste.You now have enough potential to build your own server for any purpose.(For God's sake dont make IRC yet,just add more commands and polish and some status display funtions) --------------------------------Very boring.Diplomats use it a lot.Nah computer potocols are much more interesting.It's a specified way in which a client and a server talk. Eg of a protocolWhat !!! that's just a structure.Well my friend deplomats never say even a simple thing simply you know.Some times life is very simple.Now how do you use this.Simple,any file i/o. send(sock,(char*)&prt_buff,sizeof(chat_protocol),0);It's as simple as that.This was a very simplistic view.I dont really care to go into the jargon when dealing with newbies. Actually a protocol define how large a transmission is,what it is made up of,and where to find what. Eg.The first byte to the 2nd byte will contain an integer containing an id.The next 10 byte will contain the nick name.The rest will contain the message.That how a protocol would be on paper so that others can implement it in their programms which may not be in C/C++ and then they will still be able to communicate with your server.C++ make this stuff quite easy as you can see :-). Of course there can be sub-protocols as well.The string terminator NULL ('\0') is another protocol you could say.It tells us where the string ends.Aowsome eh ? --------------------------------Well you know diplomats they never say anything directly and a lot of things said are not what they seem at the surface and maybe more shallow or deeper that you think.Never trust them blindly. Let me drive it home.Look at the chat_protocol above.Take the msg char variable.Now if you use cout<< it should display some text.But suppose a client has filled the entire 100 bytes with charA without a \0.What happens then.Your server will happily start reading the string, cross the limit and go into restricted parts till it hits a \0 or CRASHES !!.A simple buffer overflow exploit. Always be careful with read/write limits.This should be enough to get you worried so when you make your servers keep such things in mind.Always. [From personal experiance.When I used to work on a simple chat server I noticed that I could over write a part of memory to get past restrictions by simply setting a huge nickname.It over wrote an int which stored my current permission.The permission check funtion used to give normal permission as default.ie if(check)As far as possible dont do that and handle only conditions which can be predicted.Everything else should generate an error message and any possible action like disconnecting the client] That's a wrap folks.You know have a little above the beginners level of knowledge of building servers and it various factors and concerns. [You should be able to find the full source of the chat server on my site,compare it with yours] Name: Aaron M.(a.k.a FireNet)- Burn Out /*">"£"£)£")£"$"£("£&^£" [Exit notes:Well you should have got a nice overview of building servers quickly and in a cut-trought fasion.I will post some compleated code and and few notes concerning a few things which I have not really dealt with,and links to more resources of course] |
| ||
| Re: Winsock Multi-Client Servers Here is the server made by Aaron Anderson (to him is this tutorial dedicated) exactly how it was sent to me.Compare it with your code. I would like to add the Anderson has an excellent coding style and great potential as a coder.He is dedicated to his work and very through.I wish him very best.This server is done very well and is no copy paste job. /* |
| ||
| Re: Winsock Multi-Client Servers You #include <stdio.h> twice. Anyway, besides that little error, this is just the thing I have been looking for. Thanks, mate! |
| ||
| Re: Winsock Multi-Client Servers Hello, I tried to use that code, written by FireNet and mr Anderson. Actually I am studiying socket networking for a while now. I allredy wrote a working default (blocking) server and client. The problem is, that I cannot connect to that (non-blocking) server with echo client, also written in previous post by mr. Anderson. The client always prints "SERVERUNAVALILIBLEEXIT SIGNAL: 999" which probbably means, that client connect function call returns -1. If I watch server behavior, and it doesnt write anything. So it looks like, the server doesn't get any connecting client from network. I'd be really glad when somebody could help me by that problem. I work in Vista, and tried allredy in localhost mode (server and client on same computer), than I tried also to have server on other computer in LAN (and I changed server IP address in client) and still nothing works. I read about function accept, but really don't know how to use it and as written in previous posts, the code should work such, as it is written allredy. Many thanks for help, Domen Zupančič |
| All times are GMT -4. The time now is 2:49 pm. |
Forum system based on vBulletin Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
©2003 - 2009 DaniWeb® LLC