Happy New Year to you on the first day
has been a friend to ask the related questions, recently there is time in the breeze IM based on the realization of peer-to communication, sharing to everyone, I hope you criticize correct.
SOURCE Download (contains only source code, no plug-in ads:) database Download database and the first version of the same unchanged
We know that in the network communication, if all communication through the server forwarding, will increase the burden of the server, if the implementation of peer-to, direct communication between clients, such as chat or transfer files are no longer through the server, but the direct communication between the client, will effectively reduce the burden of the server, improve the efficiency of the program.
This section related to the peer, refers to the TCP protocol, in the local area network implementation of peer-to-peer, WAN is not involved in the temporary.
This demo is based on the networkComms2.3.1 Open source communication framework from the UK
How it works-through the server, establish peer-to-peer channels between clients, after which communication between clients can be detached from the server
The process is as follows:
The internal communication mechanism of the NETWORKCOMMS communication framework makes it very simple for us to achieve the communication between peers.
(1): server starts listening
(2): the client, start to connect the server, then also began to listen to work, in fact, become a server . During the connection process, the client is randomly assigned a port to complete communication with the server. After the connection is complete, we get the IP of the client and the port that communicates with the server, and the client listens on this port, that is, each client listens and has all the characteristics of the server.
Analog Code:
New ConnectionInfo (" server IP" " Server port "); //Client connection to the server Connection newtcpconnection = tcpconnection.getconnection (conninfo); after the client/server connection is successful, the local port is started listening, and the client is also known as a server that can listen. Tcpconnection.startlistening (Conninfo.localendpoint);
(3): Each client needs to maintain a "connect-to-peer" table
We do this with a static class that can see the common class
Store user IDs and corresponding connection references in the dictionary
Public Static dictionary<stringnew dictionary<string, connection> ();
Public Static voidAdduserconn (stringUserID, Connection conn) {Lock(Dictlocker) {if(Userconnlist.containskey (UserID)) {Userconnlist.remove (UserID); } userconnlist.add (Userid,conn); } } Public Static BOOLContainsuserconn (stringUserID) {Lock(Dictlocker) {if(Userconnlist.containskey (UserID)) {return true; }Else{return false; } } } Public StaticConnection Getuserconn (stringUserID) {Lock(Dictlocker) {if(Userconnlist.containskey (UserID)) {returnUserconnlist[userid]; }Else{return NULL; } } } Public Static voidRemoveuserconn (stringUserID) {Lock(Dictlocker) {if(Userconnlist.containskey (UserID)) {Userconnlist.remove (UserID); } } }
related Operation Methods
(4): After the client successfully logs in, get all the local endpoint (IP and port) of all the other client users online (i.e., the endpoint that the other clients are listening in step one) and connect
"1" Client A and other clients connected one by one, after successful connection, client A add the other user ID and connection reference to the local peer-to-channel dictionary
"2" Client a Send a message type "setupp2pmessage" message, to each other, so that the other side to add the corresponding record into the peer dictionary
"3" When the client is connected with other users, client A is "client", the other client is "server side", so at the 2 end of the peer channel, there is always "client" and the other end is "server".
With the NETWORKCOMMS communication framework, this kind of conceptual distinction does not affect the communication of peer-to-peer channels.
When client a communicates with other clients, either as "client" or "server", as long as there is a TCP long connection with the other party.
"4" This is a "server" built by the client to communicate with each other, with all the functions of the real server, the corresponding "Heartbeat detection" and "connection" maintenance and so on.
The following code: After a client logs in, gets all the online users and connects with it, sends a "SETUPP2PMESSAG" type message to the other after the connection is complete. Through this process, the "peer-to" connection between each other will be established.
Private voidGetp2pinfo () {//From the server side, get information about all online users (user ID, corresponding local endpoint, in the first step, the client and the server after the successful connection, has already started listening on this endpoint)ilist<useridendpoint> userinfolist = common.tcpconn.sendreceiveobject<ilist<useridendpoint>> ("Getp2pinfo","Resp2pinfo", the,"getp2p");//Traverse all online usersforeach(Useridendpoint UserInfoinchUserinfolist) {Try{if(Userinfo.userid! = Common.userid) {//write log in root directoryLoginfo.logmessage ("Ready to build"+ Userinfo.userid +":"+ userinfo.ipaddress +":"+ userInfo.Port.ToString (),"P2pinfo");//Create connection Information classConnectionInfo Conninfo =NewConnectionInfo (userinfo.ipaddress, Userinfo.port);//The client as the server corresponding connectionConnection newtcpconnection = tcpconnection.getconnection (Conninfo); Common.adduserconn (Userinfo.userid, newtcpconnection); Setupp2pcontract contract =NewSetupp2pcontract (); Contract. UserID = Common.userid;//after the peer channel is opened, send a message to the other user, so that when the other user receives the message, establish a peer -to channelNewtcpconnection.sendobject ("Setupp2pmessage", contract);//write log in root directoryLoginfo.logmessage ("has been established"+ Userinfo.userid +":"+ userinfo.ipaddress +":"+ userInfo.Port.ToString (),"P2pinfo"); } }Catch{ } } }
In the above code, we put the relevant peer channel into the "P2PINFO.txt file" under the Message writer folder to facilitate the observation of the creation of the peer-to message channel. and send messages through the peer channel
(5): send message via peer channel
When a client sends a message, it checks to see if there is a peer channel with the other, and if there is a message sent through a peer connection, it is sent via the server
For example, when sending a chat message, first check if there is a peer channel
Private voidChatcontrol1_begintosend (stringContent) { This. Chatcontrol1.showmessage (Common.username, DateTime.Now, content,true);//get the corresponding peer channel from the client commonConnection p2pconnection = Common.getuserconn ( This. friendID);if(P2pconnection! =NULL) {Chatcontract Chatcontract =NewChatcontract (); Chatcontract.userid = Common.userid; Chatcontract.username = Common.username; Chatcontract.destuserid = This. friendID; Chatcontract.destusername = This. friendID; Chatcontract.content = Content; Chatcontract.sendtime = DateTime.Now; P2pconnection.sendobject ("Clientchatmessage", chatcontract); This. Chatcontrol1.focus (); Loginfo.logmessage ("send a message through the peer-to channel, the current user ID is"+common.userid,"P2pinfo"); }Else{Chatcontract Chatcontract =NewChatcontract (); Chatcontract.userid = Common.userid; Chatcontract.username = Common.username; Chatcontract.destuserid = This. friendID; Chatcontract.destusername = This. friendID; Chatcontract.content = Content; Chatcontract.sendtime = DateTime.Now; Common.TcpConn.SendObject ("Chatmessage", chatcontract); This. Chatcontrol1.focus (); Loginfo.logmessage ("Server forwarding Messages","P2pinfo"); } }
(6) Out -of-peer channel logoff
When a client is dropped, we want to log it off from the peer channel of the other corresponding client.
Method:
The server passes the heartbeat detection, knowing that a connection is dropped and sends a message to all other clients.
Private voidUserstatenotify (stringUseridBOOLOnLine) {Try{//User state Contract classUserstatecontract userState =NewUserstatecontract (); Userstate.userid = UserID; Userstate.online = OnLine; Ilist<shortguid> Alluserid;Lock(Synclocker) {//get the user ID in all user dictionariesAlluserid =NewList<shortguid> (usermanager.values); }//send a user's online status to all users foreach(Shortguid NetIDinchAlluserid) {list<connection> result = Networkcomms.getexistingconnection (NetID, C ONNECTIONTYPE.TCP);if(result.) Count >0&& result[0].connectioninfo.networkidentifier = = NetID) {result[0]. SendObject ("userstatenotify", userState); } } }Catch(Exception ex) {Logtools.logexception (ex,"mainform.userstatenotify"); } }
server-side code to send users online or offline messages
Client code:
Networkcomms.appendglobalincomingpackethandler<userstatecontract> ("userstatenotify ", incominguserstatenotify);
Private voidIncominguserstatenotify (packetheader header, Connection Connection, Userstatecontract userstatecontract) {if(Userstatecontract.online) {Lock(Synclocker) {//This section, dealing with users on-line, regardless of the peer channelCommon.getdicuser (Userstatecontract.userid). state = Onlinestate.online; } }Else{Lock(Synclocker) {Common.getdicuser (Userstatecontract.userid). state = Onlinestate.offline;//Delete this user-related peer channel when a user is offlineCommon.removeuserconn (Userstatecontract.userid); } } }
I hope you enjoy the short introduction to this place.
"Open Source Download" C # Chat program written by Breeze IM version 2 increases LAN-to-peer communication