Chapter103:AsynchronousSocket

No Comments

Byusingasynchronoussocketsaservercanlisteningforincomingconnectionsanddosomeotherlogicinthe mean time in contrast to synchronous socket when they are listening they block the main thread and the application is becoming unresponsive an will freeze until a client connects.

Section103.1:AsynchronousSocket(Client/Server)example

ServerSideexample

CreateListenerforserver

Start of with creating an server that will handle clients that connect, and requests that will be send. So create an Listener Class that will handle this.

classListener

{

publicSocketListenerSocket;//Thisisthesocketthatwilllistentoanyincomingconnections

publicshortPort=1234;//onthisportwewilllisten

publicListener()

{

ListenerSocket=newSocket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);

}

}

FirstweneedtoinitializetheListenersocketwherewecanlistenonforanyconnections.Wearegoingtousean Tcp Socket that is why we use SocketType.Stream. Also we specify to witch port the server should listen to

Then we start listening for any incoming connections.

Thetreemethodsweusehereare:

  1. ListenerSocket.Bind();

ThismethodbindsthesockettoanIPEndPoint.Thisclasscontainsthehostandlocalorremoteport information needed by an application to connect to a service on a host.

2. ListenerSocket.Listen(10);

Thebacklogparameter specifiesthenumber ofincoming connectionsthatcan bequeued foracceptance.

3. ListenerSocket.BeginAccept();

The server will start listening for incoming connections and will go on with other logic. When there is an connection the server switches back to this method and will run the AcceptCallBack methodt

publicvoidStartListening()

{

try

{

MessageBox.Show($”Listeningstartedport:{Port}protocoltype:

{ProtocolType.Tcp}”);

ListenerSocket.Bind(new IPEndPoint(IPAddress.Any, Port));

ListenerSocket.Listen(10);

ListenerSocket.BeginAccept(AcceptCallback,ListenerSocket);

}

catch(Exceptionex)

{

thrownewException(“listeningerror”+ex);

}

}

Sowhenaclientconnectswecanacceptthembythismethod:

Threemethodsweeusehereare:

  1. ListenerSocket.EndAccept()

WestartedthecallbackwithListener.BeginAccept()endnowwehavetoendthatcallback.TheEndAccept()methodacceptsanIAsyncResultparameter,thiswillstorethestateoftheasynchronous method,Fromthisstatewecanextractthesocketwheretheincomingconnectionwascomingfrom.

2. ClientController.AddClient()

With the socket we got from EndAccept()we create an Client with an own made method (code ClientControllerbelowserverexample).

3. ListenerSocket.BeginAccept()

We need to start listening again when the socket is done with handling the new connection. Pass in the methodwhowillcatchthiscallback.AndalsopassinttheListenersocketsowecanreusethissocketfor upcoming connections.

publicvoidAcceptCallback(IAsyncResultar)

{

try

{

Console.WriteLine($”AcceptCallBackport:{Port}protocoltype:{ProtocolType.Tcp}”); SocketacceptedSocket=ListenerSocket.EndAccept(ar); ClientController.AddClient(acceptedSocket);

ListenerSocket.BeginAccept(AcceptCallback,ListenerSocket);

}

catch(Exceptionex)

{

thrownewException(“BaseAccepterror”+ex);

}

}

NowwehaveanListeningSocketbuthowdowereceivedatasendbytheclientthatiswhatthenextcodeis showing.

CreateServerReceiverforeachclient

FirstofcreateareceiveclasswithaconstructorthattakesinaSocketasparameter:

publicclassReceivePacket

{

privatebyte[]_buffer;privateSock

et_receiveSocket;

publicReceivePacket(SocketreceiveSocket)

{

_receiveSocket=receiveSocket;

}

}

Inthenextmethodwefirststartoffwithgivingthebufferasizeof4bytes(Int32)orpackagecontainstoparts

{lenght, actual data}.So thefirst 4bytes wereserve forthe lenghtof the datathe restfor theactual data.

NextweuseBeginReceive()method.Thismethodisusedtostartreceivingfromconnectedclientsandwhenitwill receivedataitwillruntheReceiveCallbackfunction.

publicvoidStartReceiving()

{

try

{

_buffer=newbyte[4];

_receiveSocket.BeginReceive(_buffer,0,_buffer.Length,SocketFlags.None,

ReceiveCallback,null);

}

catch{}

}

privatevoidReceiveCallback(IAsyncResultAR)

{

try

{

//ifbytesarelessthan1takesplacewhenaclientdisconnectfromtheserver.

//SoweruntheDisconnectfunctiononthecurrentclient

if(_receiveSocket.EndReceive(AR)>1)

{

//Convertthefirst4bytes(int32)thatwereceivedandconvertittoanInt32

(thisisthesizeforthecomingdata).

_buffer=newbyte[BitConverter.ToInt32(_buffer,0)];

//Nextreceivethisdataintothebufferwithsizethatwedidreceivebefore

_receiveSocket.Receive(_buffer,_buffer.Length,SocketFlags.None);

//Whenwereceivedeverythingitsontoyoutoconvertitintothedatathatyou’ve

send.

//Forexamplestring,intetc…inthisexampleIonlyusetheimplementationfor

sendingandreceivingastring.

socket.

//Convertthebytestostringandoutput itinamessagebox stringdata=Encoding.Default.GetString(_buffer);MessageBox.Show(data);

//Nowwehavetostartalloveragainwithwaitingforadatatocomefromthe

StartReceiving();

}

else

{

Disconnect();

}

}

catch

{

// if exeption is throw check if socket is connected because than you can startreive againelseDissconect

if(!_receiveSocket.Connected)

{

Disconnect();

}

else

{

StartReceiving();

}

}

}

privatevoidDisconnect()

{

//Closeconnection

_receiveSocket.Disconnect(true);

//Nextlineonlyapplyfortheserversidereceive

ClientController.RemoveClient(_clientId);

//NextlineonlyapplyontheClientSidereceive

HereyouwanttorunthemethodTryToConnect()

}

Sowe’vesetupaserverthatcanreceiveandlistenforincomingconnections.Whenaclientsconnectitwillbe added to a list of clients and every client has his own receive class. To make the server listen:

Listenerlistener=newListener();listener.StartListening();

SomeClassesIuseinthisexample

classClient

{

publicSocket_socket{get;set;}

publicReceivePacketReceive{get;set;}

publicintId{get;set;}

publicClient(Socketsocket,intid)

{

Receive=newReceivePacket(socket,id);

Receive.StartReceiving();

_socket=socket;

Id=id;

}

}

staticclassClientController

{

publicstaticList<Client>Clients=newList<Client>();

publicstaticvoidAddClient(Socketsocket)

{

Clients.Add(newClient(socket,Clients.Count));

}

publicstaticvoidRemoveClient(intid)

{

Clients.RemoveAt(Clients.FindIndex(x=>x.Id==id));

}

}

ClientSideexample

Connectingtoserver

Firstofallwewanttocreateaclasswhatconnectstotheservertenamewegiveitis:Connector:

classConnector

{

privateSocket_connectingSocket;

}

Next Method for this class is TryToConnect() Thismethodgothafewinterestinthings:

  1. Createthesocket;
  2. Next Iloopuntil thesocketis connected
  3. EveryloopitisjustholdingtheThreadfor1secondwedon’twanttoDOStheserverXD
  4. With Connect()it will try to connect to the server. If it fails it will throw an exception but the wile will keep the programconnectingtotheserver.YoucanuseaConnectCallBackmethodforthis,butI’lljustgoforcallinga method when the Socket is connected.
  5. NoticetheClientisnowtryingtoconnecttoyourlocalpconport1234.

publicvoidTryToConnect()

{

_connectingSocket=newSocket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);

while(!_connectingSocket.Connected)

{

Thread.Sleep(1000);

try

{

_connectingSocket.Connect(newIPEndPoint(IPAddress.Parse(“127.0.0.1”),1234));

}

catch{}

}

SetupForReceiveing();

}

}

privatevoidSetupForReceiveing()

{

//ViewClientClassbottomofClientExample

Client.SetClient(_connectingSocket); Client.StartReceiving();

}

Sendingamessagetotheserver

SonowwehaveanalmostfinishorSocketapplication.Theonlythingthatwedon’thavejetisaClassforsendinga message to the server.

publicclassSendPacket

{

privateSocket_sendSocked;

publicSendPacket(SocketsendSocket)

{

_sendSocked=sendSocket;

}

publicvoidSend(stringdata)

{

try

{

/*whathapendshere:

  1. Createalistofbytes
  2. Addthelengthofthestringtothelist.

Soifthismessagearrivesattheserverwecaneasilyreadthelengthofthe

comingmessage.

3. Addthemessage(string)bytes

*/

varfullPacket=newList<byte>(); fullPacket.AddRange(BitConverter.GetBytes(data.Length)); fullPacket.AddRange(Encoding.Default.GetBytes(data));

/*Sendthemessagetotheserverwearecurrentlyconnectedto.

Orpackagestuctureis{lengthofdata4bytes(int32),actualdata}*/

_sendSocked.Send(fullPacket.ToArray());

}

catch(Exceptionex)

{

thrownewException();

}

}

Finalycratetwobuttonsoneforconnectandtheotherforsendingamessage:

privatevoidConnectClick(objectsender,EventArgse)

{

Connectortpp=newConnector(); tpp.TryToConnect();

}

privatevoidSendClick(objectsender,EventArgse)

{

Client.SendString(“Testdatafromclient”);

}

TheclientclassIusedinthisexample

publicstaticvoidSetClient(Socketsocket)

{

Id=1;

Socket=socket;

Receive=newReceivePacket(socket,Id);

SendPacket=newSendPacket(socket);

}

Notice

TheReceiveClassfromtheserveristhesameasthereceiveclassfromtheclient.

Conclusion

Younowhaveaserverandaclient.Youcanworkthisbasicexampleout.Forexamplemakeitthattheserveralso can receive files or other tings. Or send a message to the client. In the server you got a list of client so when you receive something you will know from with client it came from.


Finalresult:

About us and this blog

We are a digital marketing company with a focus on helping our customers achieve great results across several key areas.

Request a free quote

We offer professional SEO services that help websites increase their organic search score drastically in order to compete for the highest rankings even when it comes to highly competitive keywords.

Subscribe to our newsletter!

More from our blog

See all posts
No Comments

Leave a Comment