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:
- 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:
- 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:
- Createthesocket;
- Next Iloopuntil thesocketis connected
- EveryloopitisjustholdingtheThreadfor1secondwedon’twanttoDOStheserverXD
- 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.
- 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:
- Createalistofbytes
- 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 postsRecent Posts
- Chapter120:YieldKeyword 20/05/2024
- Chapter119:LockStatement 19/05/2024
- Chapter118:Makingavariablethreadsafe 18/05/2024