Network-send and receive data on the network

Source: Internet
Author: User
Problem

Creating and joining a network session is one thing. But if you cannot send or receive any data, what is the purpose of a network session?

Solution

When a player connects to a session, you can store all the data to be sent in a packetwriter stream. After completing this operation, you can use the localnetworkplayer. senddata method to send this packetwriter to all players in the session.

Before a player receives data, check whether their localnetworkgamer. isdataavailable is set to true. This indicates that the data has been received and ready for processing.

Once isdataavailable is true, you can call the localnetworkgamer. receivedata method to return packetreader that contains all the data sent by another player to the local player.

Working Principle

This tutorial is based on the results of the previous tutorial. The previous tutorial allows multiple machines on the same network to communicate through one session.ProgramThe update method of the session is called simply.

Now, you will perform some actual operations in the insession status, so that your players can send some data to other players in the session. In this example, the number of minutes and seconds that the sender program runs.

Then, you listen for available data. If there is available data, you will receive two numbers, put them in a string, and display them on the screen.

To send and receive data, you need a packetwriter object and a packetreader object.CodeAdd these two variables:

 
Packetwriter writer = new packetwriter (); packetreader reader = new packetreader ();

There is no reason to use more than one packetwriter object and packetreader object in the project.

Send data to another player in the session

You need to store all the data to be sent to other players in packetwriter. This can be done by using the data as a parameter of the write method:

 
Writer. Write (gametime. totalgametime. Minutes); writer. Write (gametime. totalgametime. Seconds );

After storing all the data to packetwriter, you can use the senddata method of the local player to send it to all other users:

 
Localnetworkgamer localgamer = networksession. localgamers [0]; localgamer. senddata (writer, senddataoptions. None );

The senddataoptions parameter will be explained at the end of the tutorial. More importantly, senddata has an overload method that only sends data to the specified player rather than all players in the session.

The preceding operations are required to send data to other players in the session.

Receive data from another player in the session

Receiving data from other players is generally a reverse process: Call the receivedata method of the local player, which returns a packetreader containing the data sent by other players. Call one of the packetreader. Read methods to obtain data from packetreader:

 
Networkgamer sender; localgamer. receivedata (reader, out sender); string playername = sender. gamertag; int minutes = reader. readint32 (); int seconds = reader. readint32 ();

The receivedata method stores data in the packetreader stream. Players who send data to you will store the data in the second parameter so that you can know who the data comes from.

When reading data from packetreader, make sure to read the data in the same order as sending. Besides, because packetreader only contains byte streams, you need to tell which object you want to build from the byte. For example, an integer requires fewer bytes than a matrix, so you need to tell you which type of object you want to restore at some time.

In this example, the minutes and seconds are integers, so you want to reconstruct two integers from the byte stream. Let's take a look at the different read methods of packetreader. Pay attention to which object is supported. If you want to reconstruct the matrix, you should use the readmatrix method to reconstruct the float, readdouble method to reconstruct the double, readint16 method to reconstruct the short.

Localgamer. isdataavailable

If multiple players send data to you, multiple byte streams may need to be read. This also happens when other players call senddata more frequently than when you call receivedata.

In this case, you can query the localgamer. isdataavailable attribute, because this attribute is true if a byte stream is waiting for a local game.

As long as the data is available to your players, the following code will receive the gamertag attribute of a new packetreader and read the sent data. Then, the minutes and seconds of running the player program will be read from packetreader.

While (localgamer. isdataavailable )... {networkgamer sender; localgamer. receivedata (reader, out sender); string gamertime = ""; gamertime + = sender. gamertag + ":"; gamertime + = reader. readint32 () + "M"; gamertime + = reader. readint32 () + "S"; gamertimes [sender. gamertag] = gamertime ;}

To let this example actually do something, the data is converted to a string called gamertime, which is stored in a dictionary. Dictionary is the default generic. Net query table, which can be created using the following code:

 
Dictionary <string, string> gamertimes = new dictionary <string, string> ();

The previous Code will create a data item in dictionary and send it to the gamer. When receiving new data from a player, the corresponding data items in the dictionary will be updated. You can display the strings in the dictionary on the screen in the draw method.

When a player leaves a session, you need to remove the corresponding data items from the dictionary, which can be handled in the gamerleft event:

 
Void gamerlefteventhandler (Object sender, gamerlefteventargs e )... {log. add (E. gamer. gamertag + "left the current session"); gamertimes. remove (E. gamer. gamertag );}
Senddataoptions

When you send data to other players in the session, the order in which you expect the information to arrive at the recipient is the same as that in which the message is sent, but based on the Internet principle, your information may arrive in a different or even worse order than the sending order. Some data may not be transmitted at all!

Fortunately, you can specify two important coefficients for the sent packets. before using them, you need to know what they are, what are the benefits, and more importantly, what are their disadvantages:

    • Order of arrival: is the order in which packets are received the same as that in which packets are sent?
    • Security (reliability): Is the data you send critical? Can the game continue if data packets are lost?

The above two questions are not about whether or not. There are four possibilities available. Localnetworkgamer. senddata can use senddataoptions as the second parameter. This parameter allows you to specify one of the four cases:

    • Senddataoptions. None: The sent data is not critical, and the order in which you receive data is irrelevant.
    • Senddataoptions. Inorder: the order in which data is received must be the same as the order in which data is sent, but some data packets are lost.
    • Senddataoptions. Reliable: In contrast to senddatoptions. Inorder, your data is critical and all the data you send must reach the recipient. However, whether the order of received data is the same as that of sent data does not matter.
    • Senddataoptions. reliableinorder: All data must arrive at the receiver in the same order as the sent data.

Not very difficult. I chose the last one! Some options have some disadvantages and are explained as follows:

    • Senddataoptions. None: No speed loss. Only data can be sent successfully.
    • Senddataoptions. Inorder: before sending data, all data packets are assigned a sequence number. The receiver checks the serial number. If packet a is received after a newer packet B, packet a is discarded. This is a simple check method. It takes almost no time, but some data may be discarded even if it reaches its destination.
    • Senddataoptions. Reliable: the receiver checks which packet is lost. When data packet C is lost from the Data Packet Flow abde, the receiver will require the sender to resend data packet C. Meanwhile, data packets D and E can be accessed in xNa code.
    • Senddataoptions. reliableinorder: This option is used only when your data needs it. When the receiver's normal packet C is lost from the flow abde, it will let the sender resend the packet C. This time, the subsequent data packets D and E will not be transmitted to xNa by the receiver until the data packet C is also successfully transmitted. This will cause latency because all subsequent data packets will be stored in the memory until data packet C is re-sent and received before being passed to the xNa program.

The general principle is that for most data, senddataoptions. Inorder is safe and do not use senddataoption. reliableinorder.

Senddataoption. Chat

Before sending data, you must remember that the chat messages sent on the Internet cannot be encrypted and are prohibited by law.

By default, data sent using the localgamer. senddata method is encrypted. You must use senddataoptions. chat to indicate that xNa does not encrypt chat information. You can also use the senddataoption combination as follows:

 
Localgamer. senddata (write, sengdataoptions. Chat | senddataoptions. Reliable );

Note that you can send Encrypted and unencrypted information. If you do this, the sorted chat information is only sorted by chat data rather than encrypted data. For example, let's take a look at the data information, chat information, and data information when sending the first message, as shown in the left figure 8-1.

Figure 8-1 send four data packets sequentially (left) and four data receiving Methods

The right figure of figure 8-1 shows the four possible ways in which the data reaches the acceptor. In case a, the data arrives in the same order as the sent data. In case B and C, the packet sequence has changed. However, in both cases, the first chat packet a is received before the second chat packet C, the first packet B is before the second packet D.

Because two packets and two chat packets can be sent in one frame, you need to ensure that they are mixed at the receiving end. One method is to add a small description to the packets before sending them, indicates whether they are data packets or chat packets. Check the following code. D indicates a data packet, and C indicates a chat packet:

 
Writer. write ("D"); writer. write (gametime. totalgametime. minutes); writer. write (gametime. totalgametime. seconds); localnetworkgamer localgamer = networksession. localgamers [0]; localgamer. senddata (writer, senddataoptions. reliableinorder); writer. write ("C"); writer. write ("this is a chat message from" + localgamer. gamertag); localgamer. senddata (writer, senddataoptions. chat | senddataoptions. reliableinorder );

At the receiving end, simply check whether the data packet is D or C and process the corresponding data packet:

While (localgamer. isdataavailable )... {networkgamer sender; localgamer. receivedata (reader, out sender); string messagetype = reader. readstring (); If (messagetype = "D ")... {string gamertime = ""; gamertime + = sender. gamertag + ":"; gamertime + = reader. readint32 () + "M"; gamertime + = reader. readint32 () + "S"; gamertimes [sender. gamertag] = gamertime;} else if (messagetype = "C ")... {lastchatmessage [sender. gamertag] = reader. readstring ();}}
Multiple local players

If multiple players are connected to the same machine, you need to send and accept data through the iterator.

Sending data to all players is easy:

 
// Send data from all local players to all other players in sessionforeach (localnetworkgamer localgamer in networksession. localgamers )... {writer. write (gametime. totalgametime. minutes); writer. write (gametime. totalgametime. seconds); localgamer. senddata (writer, senddataoptions. reliableinorder );}

Remember, you can use an overload method of senddata to send data to only one specified player.

It is not difficult to receive data. You only need to loop the code until isdataavailable of all local players is false:

 
Foreach (localnetworkgamer localgamer in networksession. localgamers )... {While (localgamer. isdataavailable )... {networkgamer sender; localgamer. receivedata (reader, out sender); string gamertime = localgamer. gamertag + "received from"; gamertime + = sender. gamertag + ":"; gamertime + = reader. readint32 () + "M"; gamertime + = reader. readint32 () + "S"; gamertimes [sender. gamertag] = gamertime ;}}
Code

The following is the update method code, including the extended insession status. All players on your machine send data to all players in the session. Then, they will receive the data sent to them.

If you run this code on multiple machines, they will automatically connect to the session created on the first machine. Then, start sending the time information and display the received data on the screen in the draw method.

Protected override void Update (gametime )... {If (gamepad. getstate (playerindex. one ). buttons. back = buttonstate. pressed) This. exit (); If (this. isactive )... {Switch (currentgamestate )... {Case gamestate. signin :... {If (gamer. signedingamers. count <1 )... {guide. showsignin (1, false); log. add ("opened user signin interface");} else... {currentgamestate = gamestate. searchsession; log. add (gamer. signedingamers [0]. gamertag + "logged in-Proceed to searchsession") ;}} break; Case gamestate. searchsession :... {availablenetworksessioncollection activesessions = networksession. find (networksessiontype. systemlink, 4, null); If (activesessions. count = 0 )... {currentgamestate = gamestate. createsession; log. add ("no active sessions found-Proceed to createsession");} else... {availablenetworksession networktojoin = activesessions [0]; networksession = networksession. join (networktojoin); string mystring = "joined session hosted by" + networktojoin. hostgamertag; mystring + = "with" + networktojoin. currentgamercount. tostring () + "players"; mystring + = "and" + networktojoin. openpublicgamerslots. tostring () + "Open player slots. "; log. add (mystring); hooksessionevents (); currentgamestate = gamestate. insession ;}} break; Case gamestate. createsession :... {networksession = networksession. create (networksessiontype. systemlink, 4, 16); networksession. allowhostmigration = true; networksession. allowjoininprogress = false; log. add ("new session created"); hooksessionevents (); currentgamestate = gamestate. insession;} break; Case gamestate. insession :... {// send data from all local players to all other players in session foreach (localnetworkgamer localgamer in networksession. localgamers )... {writer. write (gametime. totalgametime. minutes); writer. write (gametime. totalgametime. seconds); localgamer. senddata (writer, senddataoptions. reliableinorder);} // receive data from all other players in session foreach (localnetworkgamer localgamer in networksession. localgamers )... {While (localgamer. isdataavailable )... {networkgamer sender; localgamer. receivedata (reader, out sender); string gamertime = localgamer. gamertag + "received from"; gamertime + = sender. gamertag + ":"; gamertime + = reader. readint32 () + "M"; gamertime + = reader. readint32 () + "S"; gamertimes [sender. gamertag] = gamertime;} networksession. update ();} break;} base. update (gametime );}}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.