Game biasanya memiliki koneksi panjang dan protokol khusus, dan tidak menggunakan protokol HTTP. Saya tidak akan berbicara tentang Bio, Nio, AIO, dll., Periksa informasinya sendiri.
Saya menggunakan Spring+Netty untuk mengatur server game yang sederhana
Ide: 1. Paket Protokol dan Protokol Kustom; 2.spring+integrasi netty; 3.Half-Packet Sticking Processing, Mekanisme Detak Jantung, dll.; 4. Distribusi Pernyataan (Saat Ini, Saya Melakukan Mode Singleton)
Berikutnya adalah untuk pengujian, strukturnya adalah sebagai berikut
Pertama, sesuaikan header paket
Header.java
paket com.test.netty.message; / ** * header.java * header protokol khusus * @author JaneHuang * @Version 1.0 */ header kelas publik {tag byte pribadi; /* Encode*/ private byte encode; /* Enkripsi*/ enkripsi byte pribadi; /*Bidang lain*/ byte private EXTENT1; /*2*/ byte privat lainnya 2; /*SessionId*/ private string sessionID; /*Panjang paket*/ panjang int privat = 1024; /*Perintah*/ private int cammand; header publik () {} header publik (string sessionId) {this.encode = 0; this.encrypt = 0; this.SessionId = sessionId; } header publik (tag byte, encode byte, enkripsi byte, enkripsi byte, byte extend1, byte stagar2, string sessionId, panjang int, int peluru) {this.tag = tag; this.encode = encode; this.encrypt = enkripsi; this.extend1 = extend1; this.extend2 = extend2; this.SessionId = sessionId; this.length = panjang; this.cammand = cammand; } @Override Public String ToString () {return "header [tag =" + tag + "encode =" + encode + ", encrypt =" + encrypt + ", extend1 =" + extend1 + ", extend2 =" + extend2 + ", sessionid =" + sessionID + ", length =" + length + ", cammand =" + " +" + " +"] ", length =" + length + ", cammand =" + " +" + " +" + ", cammand =" + " } public byte getTag () {tag return; } public void settag (tag byte) {this.tag = tag; } public byte getencode () {return encode; } public void setencode (byte encode) {this.encode = encode; } public byte getEncrypt () {return encrypt; } public void setencrypt (enkripsi byte) {this.encrypt = encrypt; } public byte getExtend1 () {return stagar1; } public void setextend1 (byte extend1) {this.extend1 = extend1; } public byte getExtend2 () {return stagar2; } public void setextend2 (byte extend2) {this.extend2 = extend2; } public string getSessionId () {return sessionId; } public void setSessiesId (String sessionId) {this.SessionId = sessionId; } public int getLength () {panjang kembali; } public void setLength (int panjang) {this.length = length; } public int getCammand () {return campmand; } public void setCammand (int campmand) {this.cammand = campmand; }} Saya cukup memproses penggunaan string ke bytecode. Umumnya, banyak game menggunakan Seri Probuf untuk berubah menjadi biner
Pesan.java
paket com.test.netty.message; impor io.netty.buffer.bytebuf; impor io.netty.buffer.unpooled; impor java.io.bytearrayoutputStream; impor java.io.ioException; impor java.io.unsupportedencodingException; impor com.test.netty.decoder.messagedecoder; / ** * message.java * * @author janehuang * @Version 1.0 */ pesan kelas publik {header header pribadi; data string pribadi; header publik getHeader () {return header; } public void setheader (header header) {this.header = header; } public String getData () {return data; } public void setData (string data) {this.data = data; } pesan publik (header header) {this.header = header; } pesan publik (header header, data string) {this.header = header; this.data = data; } public byte [] tobyte () {bytearrayoutputStream out = new ByteArrayOutputStream (); out.write (MessageDecoder.package_tag); out.write (header.getencode ()); out.write (header.getEncrypt ()); out.write (header.getextend1 ()); out.write (header.getextend2 ()); byte [] bb = byte baru [32]; byte [] bb2 = header.getSessionId (). getBytes (); untuk (int i = 0; i <bb2.length; i ++) {bb [i] = bb2 [i]; } coba {out.write (bb); byte [] bbb = data.getBytes ("UTF-8"); out.write (inttobytes2 (bbb.length)); out.write (inttobytes2 (header.getCammand ())); out.write (BBB); out.write ('/n'); } catch (UnsupportedEncodingException e) {// TODO Auto-Enchenerated Catch Block E.PrintStackTrace (); } catch (ioException e) {// TODO AUTO-ENCEALATED Catch Block E.PrintStackTrace (); } return out.tobyteArray (); } public static byte [] inttobyte (int newInt) {byte [] intbyte = byte baru [4]; intbyte [3] = (byte) ((newInt >> 24) & 0xff); intbyte [2] = (byte) ((newInt >> 16) & 0xff); intbyte [1] = (byte) ((newInt >> 8) & 0xff); intbyte [0] = (byte) (newInt & 0xff); Return Intbyte; } public static int bytestoint (byte [] src, int offset) {int value; value = (int) ((src [offset] & 0xff) | ((src [offset + 1] & 0xff) << 8) | ((src [offset + 2] & 0xff) << 16) | ((src [offset + 3] & 0xff) << 24)); nilai pengembalian; } public static byte [] inttobytes2 (nilai int) {byte [] src = byte baru [4]; src [0] = (byte) ((nilai >> 24) & 0xff); src [1] = (byte) ((nilai >> 16) & 0xff); src [2] = (byte) ((nilai >> 8) & 0xff); src [3] = (byte) (nilai & 0xff); mengembalikan src; } public static void main (string [] args) {bytebuf heapbuffer = unpooled.buffer (8); System.out.println (heapBuffer); BytearrayoutputStream out = bytearrayoutputStream () baru; coba {out.write (inttobytes2 (1)); } catch (ioException e) {// TODO AUTO-ENCEALATED Catch Block E.PrintStackTrace (); } byte [] data = out.tobyteArray (); heapbuffer.writebytes (data); System.out.println (heapBuffer); int a = heapbuffer.readint (); System.out.println (a); }} Decoder
MessageDecoder.java
paket com.test.netty.decoder; impor io.netty.buffer.bytebuf; impor io.netty.channel.ChannelHandlerContext; impor io.netty.handler.codec.bytetomessagedecoder; impor io.netty.handler.codec.corruptedFrameException; impor java.util.list; impor com.test.netty.message.header; impor com.test.netty.message.message; / *** headerdecoder.java** @author Janeehuang* @Version 1.0*/ kelas publik MessageDecoder memperluas bytetomessagedecoder {/ ** header panjang paket **/ public static int head_lenght = 45; / ** Header Bendera **/ Public Static Final Byte Package_tag = 0x01; @Override Protected Void Decode (ChannelHandlerContext CTX, BytEBUF Buffer, List <Papen> out) melempar Exception {buffer.markReaderIndex (); if (buffer.readableBytes () <head_lenght) {throw new koruprameException ("Paket panjang masalah"); } tag byte = buffer.readbyte (); if (tag! = package_tag) {throw new koruprameException ("flag error"); } byte encode = buffer.readbyte (); Byte Encrypt = buffer.readbyte (); byte extend1 = buffer.readbyte (); byte extend2 = buffer.readbyte (); byte sessionByte [] = byte baru [32]; buffer.readbytes (sessionbyte); String sessionId = string baru (sessionByte, "UTF-8"); int panjang = buffer.readint (); int cammand = buffer.readint (); Header header = header baru (tag, encode, enkripsi, extend1, extend2, sessionid, length, cammand); byte [] data = byte baru [panjang]; buffer.readbytes (data); Pesan pesan = pesan baru (header, string baru (data, "UTF-8")); out.add (pesan); }} Encoder
Messageencoder.java
paket com.test.netty.encoder; impor com.test.netty.decoder.messagedecoder; impor com.test.netty.message.header; impor com.test.netty.message.message; impor io.netty.buffer.bytebuf; impor io.netty.channel.ChannelHandlerContext; impor io.netty.handler.codec.messagetobyteencoder; / ** * MessageCoder.java * * @author Janeehuang * @Version 1.0 */ Public Class Messageencoder memperluas MessageToByTeencoder <pesage> {@Override dilindungi void encode (ChannelHandlerContext ctx, pesan msg, byteBuf out) lemparan pengecualian {msgeader = msg.) (ByteHet out) Lemparan ECECPERION {msgeader = msg.) out.writebyte (messagedecoder.package_tag); out.writebyte (header.getEncode ()); out.writebyte (header.getEncrypt ()); out.writebyte (header.getextend1 ()); out.writebyte (header.getextend2 ()); out.writebytes (header.getSessionId (). getBytes ()); out.writeint (header.getLength ()); out.writeint (header.getCammand ()); out.writebytes (msg.getData (). getBytes ("UTF-8"))); }} server
Timeserver.java
paket com.test.netty.server; impor org.springframework.stereotype.component; impor io.netty.bootstrap.serverbootstrap; impor io.netty.buffer.bytebuf; impor io.netty.buffer.unpooled; impor io.netty.channel.channelfuture; impor io.netty.channel.channelinitializer; impor io.netty.channel.channeloption; impor io.netty.channel.eventloopgroup; impor io.netty.channel.nio.nioeventloopGroup; impor io.netty.channel.socket.socketchannel; impor io.netty.channel.socket.nio.nioserversocketchannel; impor io.netty.handler.codec.lineBasedFramedEcoder; impor com.test.netty.decoder.messagedecoder; impor com.test.netty.encoder.messageencoder; impor com.test.netty.handler.serverhandler; / ** * chatserver.java * * @author JaneHuang * @Version 1.0 */ @Component Kelas publik Timeserver {private int port = 88888; public void run () melempar InterruptedException {EventLoopGroup bossgroup = new nioeventloopGroup (); EventLoopGroup workergroup = new nioeventloopgroup (); Bytebuf heapbuffer = unpooled.buffer (8); heapbuffer.writebytes ("/r" .getbytes ()); coba {serverbootstrap b = serverbootstrap baru (); // (2) b.group (bossgroup, workergroup) .channel (nioserversocketchannel.class) // (3) .ChildHandler (ChannelInitializer baru <socketchannel> () {// (4) @Override public void initchannel (socketchannel ch) lemparan pengecualian {chrowsely (socketchannel (socketchannel () {4) {4). MessageEncoder ()). AddLast ("Decoder", New MessageDecoder ()). AddFirst (baru LineSedFamedEcoder (65535)) .AddLast (serverHandler ()); // (6) saluran f = b.bind (port) .sync (); // (7) f.channel (). CloseFuture (). Sync (); } akhirnya {workergroup.shutdowngracelly (); bossgroup.shutdowngracelly (); }} public void start (int port) melempar InterruptedException {this.port = port; this.run (); }} Prosesor dan distribusikan
ServerHandler.java
paket com.test.netty.handler; impor io.netty.channel.channelhandlerapter; impor io.netty.channel.ChannelHandlerContext; impor com.test.netty.invote.actionmaputil; impor com.test.netty.message.header; impor com.test.netty.message.message; / ** * * @author JaneHuang * */ kelas publik ServerHandler memperluas ChannelHandlapter {@Override public void channelActive (ChannelHandlerContext CTX) melempar Exception {String Content = "Saya menerima koneksi"; Header header = header baru ((byte) 0, (byte) 1, (byte) 1, (byte) 1, (byte) 0, "713f17ca614361fb257dc6741332caf2", content.getbytes ("UTF-8"). 1); Pesan pesan = pesan baru (header, konten); ctx.writeandflush (pesan); } @Override public void exceptionCaught (ChannelHandlerContext CTX, Throwable Cause) {cause.printstacktrace (); ctx.close (); } @Override public void channelRead (channelHandlerContext ctx, objek msg) melempar pengecualian {pesan m = (pesan) msg; // (1)/* permintaan distribusi*/ actionmaputil.invote (header.getCammand (), ctx, m); }} Kategori Alat Distribusi
ActionMaputil.java
paket com.test.netty.invote; impor java.lang.reflect.method; impor java.util.hashmap; impor java.util.map; Public Class ActionMaputil {private static Map <Integer, Action> peta = new HashMap <Integer, Action> (); Objek statis public Invote (kunci integer, objek ... args) melempar Exception {action action = map.get (key); if (action! = null) {metode metode = action.getMethod (); coba {return method.invoke (action.getObject (), args); } catch (Exception e) {throw e; }} return null; } public static void put (kunci integer, tindakan tindakan) {map.put (tombol, tindakan); }} Objek yang dibuat untuk distribusi
Action.java
paket com.test.netty.invote; impor java.lang.reflect.method; Tindakan Kelas Publik {Metode Metode Pribadi; objek objek pribadi; metode publik getMethod () {Metode pengembalian; } public void setMethod (metode metode) {this.method = metode; } objek publik getObject () {return objek; } public void setObject (objek objek) {this.object = objek; }}Anotasi khusus, mirip dengan @Controller di SpringMVC
Nettycontroller.java
paket com.test.netty.core; impor java.lang.annotation.Documented; impor java.lang.annotation.elementType; impor java.lang.annotation.Retention; impor java.lang.annotation.RetentionPolicy; impor java.lang.annotation.target; impor org.springframework.stereotype.component; @Retention (retentionpolicy.runtime) @Target (elementType.type) @Documented @Component public @interface nettyController {} @ReQestMapping di Spring MVC Tipe
ActionMap.java
paket com.test.netty.core; impor java.lang.annotation.Documented; impor java.lang.annotation.elementType; impor java.lang.annotation.Retention; impor java.lang.annotation.RetentionPolicy; impor java.lang.annotation.target; @Retention (retentionpolicy.runtime) @Target (elementType.method) @Documented public @interface actionMap {int key (); } Anotasi ini ditambahkan untuk menyimpan benda -benda ini dalam wadah setelah inisialisasi musim semi. Kacang ini perlu dikonfigurasi di musim semi. Kacang musim semi akan dipanggil setelah instantiasi.
ActionBeanPostProcessor.java
paket com.test.netty.core; impor java.lang.reflect.method; impor org.springframework.beans.beansException; impor org.springframework.beans.factory.config.beanpostprocessor; impor com.test.netty.invote.action; impor com.test.netty.invote.actionmaputil; ActionBeanPostProcessor kelas publik mengimplementasikan beanpostprocessor {objek publik postprocessBeforeInitialization (Object Bean, String Beanname) melempar BeansException {return bean; } Objek Publik PostProcessAfterInitialization (Object Bean, String Beanname) melempar BeansException {Method [] Method = bean.getClass (). getMethods (); untuk (metode metode: metode) {actionMap actionMap = method.getAnnotation (actionMap.class); if (actionMap! = null) {action action = new action (); action.setMethod (metode); action.setObject (bean); Actionmaputil.put (actionmap.key (), action); }} return bean; }} Instance controller
Usercontroller.java
paket com.test.netty.controller; impor io.netty.channel.ChannelHandlerContext; impor org.springframework.beans.factory.annotation.Autowired; impor com.test.model.usermodel; impor com.test.netty.core.actionmap; impor com.test.netty.core.nettycontroller; impor com.test.netty.message.message; impor com.test.service.userservice; @NettyController () Public Class UserAction {@Autowired Private UserService UserService; @ActionMap (key = 1) Login String Publik (ChannelHandlerContext CT, pesan pesan) {userModel userModel = this.userservice.findbymasteruserId (1000001); System.out.println (string.format ("Menggunakan nama panggilan: %s; kata sandi %d; konten pemancar %s", usermodel.getNickName (), usermodel.getid (), message.getData ())); kembalikan usermodel.getNickName (); }} Ingatlah untuk menambahkan ini ke file konfigurasi ApplicationContext.xml
<bean/>
Kode uji
tes paket; impor org.springframework.context.applicationContext; impor org.springframework.context.support.classpathxmlapplicationContext; impor com.test.netty.server.timeserver; tes kelas publik {public static void main (string [] args) {applicationContext ac = new classpathxmlapplicationContext ("applicationContext.xml"); TimeservererServer = ac.getBean (timeserver.class); coba {timeserver.start (8888); } catch (InterruptedException E) {// TODO Auto-Encanerated Catch Block E.PrintStackTrace (); }}} Uji sakelar uji
tes paket; impor java.io.ioException; impor java.io.outputStream; impor java.net.socket; impor java.util.scanner; impor com.test.netty.message.header; impor com.test.netty.message.message; kelas publik clienttest {public static void main (string [] args) {coba {// terhubung ke soket server soket = soket baru ("127.0.0.1", 8888); Coba {// DataOutputStream yang mengirimkan informasi ke server outputStream out = socket.getoutputStream (); // Hiasi aliran input standar, yang digunakan untuk input dari pemindai pemindai konsol = pemindai baru (System.in); while (true) {string send = scanner.nextline (); System.out.println ("Klien:" + Kirim); byte [] oleh = send.getBytes ("UTF-8"); Header header = header baru ((byte) 1, (byte) 1, (byte) 1, (byte) 1, (byte) 1, (byte) 1, "713f17ca614361fb257dc6741332caf2", by.length, 1); Pesan pesan = pesan baru (header, kirim); out.write (message.tobyte ()); out.flush (); // Kirim informasi yang diperoleh dari konsol ke server // out.writeutf ("klien:" + kirim); // Baca informasi dari server}} akhirnya {socket.close (); }} catch (ioException e) {E.PrintStackTrace (); }}}Hasil tes, oke
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.