Network online game development experience (server side)

xiaoxiao2021-03-06  40

Reserved from http://blog.9cbs.net/bromon apologized to Bromon brothers, integrated its article, else to look at the project of more than a multi-person online chess online game, I participated The entire design process of the project and completed 90% of the core code. About this project, there are many places worth talking. This series does not intend to put this project how detailed specification, that is what the design documentation should be described, I plan to talk about some things worth noting. One of this project is that the client is a mobile phone, and the user communicates with the server via mobile networks. Compared with the PC, the mobile phone has extremely weak, and network traffic is expensive. Because in addition to some of the issues of ordinary online games, these two points need to be fully considered in the design. The first is the choice of development language, because the server is Linux environment, MS technology is directly excluded, as for Mono, I really don't worry. Alternative is C and Java, Java is powerful in network capabilities, short development cycle, has a number of frames and open source support, it is not easy to write faded unacceptable code; C is fast. Comprehensive factors, C easier to turn this project into a bunch of code nightmare, we chose Java.

First, network

Online games, the first problems are of course how to communicate online. The first consideration is the HTTP protocol because all J2ME phones support this, and we certainly want to compatible users as possible. Moreover, the HTTP protocol package is already very high, do not take into account threads, synchronous, state management, connect pools, but HTTP protocols have two uncomfortable places:

◇ The agreement is stateless, this problem has been plagued many people many times. The solution I have considered is to transform the HTTP protocol. Do not close Socket after the completion of the data transfer, but this workload is very large, in the project cycle, basically Mission Impossible, not considered. Then, customers can only request data to the server by polling.

◇ The network traffic is too large. For this project, it is just an instruction between the network, but every pass is plus a bunch of unused HTTP Head, plus the client needs to be polled, this traffic is horrible for mobile phones. Simple test, according to the 0.03 yuan / K GPRS network cost calculation, a group of cards actually consume more than 1 yuan (polling per second), which is unacceptable. Maybe we can use the traffic fee of the monthly fee, but this topic has nothing to do with technology.

The above problem causes us to choose Socket, which means that we will have no web environment, and many things must be implemented: thread management, customer status monitoring, object pool, console .......... Network part intend to use Java Nio Implementation, this is a new network monitoring method, and the event-based asynchronous communication can improve performance. After each client is connected, there will be a separate SocketChannel with it, which exists in the entire survival cycle of the user. If the user is disconnected, the server will get -1 and will throw the Connection RESET exception. By capturing these two features, you can clean the relevant resources after the user unexpectedly disconnected. Since NIO is asynchronous communication, there is no complex thread management.

Second, the communication protocol

This project does not have a complex communication directive, the number of commands is limited, but there is still a key issue to pay attention: traffic. To minimize traffic, we use bytes instead of strings to save system instructions, so that traffic is reduced by half, such as using one byte to save a poke card, byte high expression color, byte low represents numbers, if 0 represents black peaches, then the black peach three should be 0x03, this requires reincarnation operation: int m = 0;

INT n = 3;

BYTE CARD = (BYTE) (M) << 4) | ((byte) n; // m left four digits, then with N left or operation

In the game, you need to pass the user's integral. This is a big integer that uses four bytes to save comparison insurance, convert the integer to the four bytes, as follows:

Public static Byte [] Translatelong (Long Mark)

{

Byte [] b = new byte [4];

For (int i = 0; i <4; i )

{

B [I] = (Byte) (Mark >>> (24 - i * 8));

}

Return B;

}

The operation of the four bytes turns back is as follows:

Public Static Long TranslateByte (Byte [] B)

{

INT MASK = 0xFF;

INT TEMP = 0;

INT RES = 0;

For (int i = 0; i <4; i )

{

RES << = 8;

Temp = b [i] & mask;

RES | = TEMP;

}

Return res;

}

Third, the database connection pool

Since there is no web environment, we need to implement a database connection pool. Apache has a project called Commons DBCP. This is a database connection pool implemented based on Apache's own object pool (Apache ", we can use it directly Apache's software is not necessarily the best, but it is greatly better than we write. Commons DBCP requires three .jar: commons-collections-3.1.jar, Commons-DBCP-

1.2.1

.jar, commons-pool-1.2.jar These three files can be downloaded under the Apache - Jakarta - Commons project, add to the project. The code constructs a database connection pool is as follows:

Import java.sql. *;

Import com.gwnet.games.antilord.util. *;

Import org.apache.commons.dbcp.connectionFactory;

Import org.apache.commons.dbcp.basicdataser;

Import org.apache.commons.dbcp.dataSourceConnectionFactory;

Private static BasicDataSource BDS = New BasicDataSource ();

Private static connectionFactory FAC = NULL;

// Initializing the connection pool

BDS.SetDriverClassName ("org.postgreSQL.Driver); // Database driver

BDS.SETURL ("JDBC: PostgreSQL: // LocalHost: 5432 / MyDB"); // Database URLBDS.SETUSERNAME ("Postgres"); // DBA Account

BDS.SETPASSWORD ("xxxxxxxx"); // password

Bds.setInitialsize (100); // Initialization connection

BDS.SETMAXIDLE (10); // Maximum number

BDS.SETMAXWAIT (1000 * 60); // Timeout Recycling Time

FAC = New DataSourceConnectionFactory (BDS); // Get the connection factory

Connection conn = fac.createConnection (); // Get a connection from the pool

Conn.close (); // Release connection, back to the pool

// Destroy the connection pool

BDS.Close ();

BDS = NULL;

FAC = NULL;

Please handle all kinds of exceptions in your own operation.

Fourth, the generation of playing cards

In the game, you need to generate a random playing card for the user. First we need to initialize a plate, put it in a HashMap, each card is represented by one byte, high as a representative color, representing the number, generates a settlement:

Private static hashmap cards = new hashmap ();

INT TMP = 0;

For (int i = 0; i <4; i ) {

For (int m = 0; M <13; m ) {

TMP = ((byte) (i) << 4) | ((byte) m); // Use a bit operation to construct a card

Cards.put (New Integer (i * 13 m), New Byte (Byte) TMP);

}

}

Cards.Put (New Integer (53), New Byte (Byte) 0x4D); // Daw

Cards.Put (New Integer (54), New Byte (Byte) 0x4e)); // Xiao Wang

How to get the N cards in it? Our approach is to generate a random number of 0-55. Use this random number to get an object from HashMap, and then remove the object from the queue to avoid repeating. Since the random number in Java is generated according to time, it is possible to cause the user to get the card is not scattered. Every user is not a joke? So when we generate random numbers, we joined a large number of calculations:

Long cardid = new long (math.Round (Math.Round (Math.Radom () * 87)%)). INTVALUE (); By modifying this big order, you can control a user's card.

V. thread

In fact, this system does not have a complex thread management, but I want to provide a console to manage the game main thread, let it stop, medium, recovery, restart, original design is the administrator to deal with thread a By managing the main thread B, friends who are familiar with the Java thread know that threads are basically unrealistic, and the simplest example, how is it destroyed B? Maybe you will say that the destroy () method of calling B is fine. Many of the online information on the Java thread is really saying, but they are all ghosts, go to see the Java source code, thread.destroy The actual code of the method is as follows: public void destroy ()

{

Throw new nosuchmethoderror ();

}

The truth is that the thread.destroy () method is not implemented from beginning to end. All people who write articles and teaches others to destroy the threads, they are going to hit the wall, and the shame is lost. The best way is to generate a B and start it, then b management survival cycle, A and B communications by using a shared method, this is a SUN recommendation.

Sixth, asynchronous messages

In the process of user playing, there are many things that need to be recorded, such as recording users' points, grade changes, record playing logs for data statistics, when the number of users is large, record this information in the database will cost resource, The user will wait for a long time after playing a game. The method of solving this problem is to use J2EE's message bean to provide an asynchronous communication mechanism. When you need to record data, the system will encapsulate a value object, send it to the J2EE container. This action is very fast. After completion, return, users can Continue, do not worry about when the message is processed. J2EE's message framework has the following characteristics:

◇ The message will be read, and only read once. The JMS frame has its own algorithm that buffers the message to the hard disk, even if the J2EE server is dead, the message will not be lost.

◇ The system uses a point-to-point Queue message queue to ensure advanced news of the same priority.

In JBoss 4.0, the deployment message bean and queue queue are easier than WebLogic 8.1, just declare message destinations in jboss.xml, if JBoss discovers that the destination does not exist, it will automatically establish one, it is very simple. . With regard to the development and deployment of the message bean, I have a special article description.

Seven, start and exit

In order for the system to have satisfactory performance, we should reuse objects as much as possible, and reduce the creation of new objects. For example, the message mentioned above, our operation is to provide a static class. Initialization when the system is started, keep the connection with the JMS server, when sending a message, do not query JNDI and generate QueueConnectionFactory, this can be improved System response speed.

On the issue of the database connection pool, we also use the same operation, initialize N connectivity when starting. But if you do not do anything when you turn off the process, it will cause JMS to throw Socket anomalies, although there is no big impact, but always seem to be professional, and the connection in the pool is not released, or may result in problems. It is best to allow the system like a console program such as JBoss, and Ctrl C will be able to perform the operation, release the resource and then exit. We can implement it by adding a hook to process / threads, and Windows programmers should be very familiar with this.

Hook should be a thread method, as follows: Public Class Hook Extends Thread

{

Public void Run ()

{

/ / Release the database connection, destroy the connection pool

// Close the connection with JMS

}

}

Add: runtime.Getruntime (). Addshutdownhook (new hook ()); then process / thread performs Hook's RUN method to clean up resources when exiting.

转载请注明原文地址:https://www.9cbs.com/read-67956.html

New Post(0)