📄 connection.java
字号:
/* * MegaMek - Copyright (C) 2005 Ben Mazur (bmazur@sev.org) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */package megamek.common.net;import java.net.*;import java.io.*;import java.util.*;import java.util.zip.GZIPInputStream;import java.util.zip.GZIPOutputStream;import megamek.common.net.marshall.PacketMarshaller;import megamek.common.net.marshall.PacketMarshallerFactory;import megamek.common.util.CircularIntegerBuffer;/** * Generic bidirectional connection between client and server */public abstract class Connection { /* * mev wrote: * This class provides common reusable code for both Client and Server. * I've constructed it from the Server & client implementations of the * read/write functionality. * * I'm not quite sure in the interface and the implementation of this * class and descendants, so comments/suggestions are welcome. */ private static PacketMarshallerFactory marshallerFactory = PacketMarshallerFactory.getInstance(); private static final int DEFAULT_MARSHALLING = PacketMarshaller.NATIVE_SERIALIZATION_MARSHALING; /** * Peer Host * Non null in case if it's a client connection */ private String host; /** * Peer port * != 0 in case if it's a client connection */ private int port; /** * Connection state */ private boolean open; /** * The socket for this connection. */ private Socket socket; /** * The connection ID */ private int id; /** * Receiver thread */ private Thread receiver; /** * Sender thread */ private Thread sender; /** * Bytes send during the connection lifecycle */ private long bytesSent; /** * Bytes received during the connection lifecycle */ private long bytesReceived; /** * Queue of <code>Packets</code> to send */ private SendQueue sendQueue = new SendQueue(); /** * Connection listeners list */ private Vector connectionListeners = new Vector(); /** * Buffer of the last commands sent; Used for debugging purposes. */ private CircularIntegerBuffer debugLastFewCommandsSent = new CircularIntegerBuffer(50); /** * Buffer of the last commands received; Used for debugging purposes. */ private CircularIntegerBuffer debugLastFewCommandsReceived = new CircularIntegerBuffer(50); /** * Type of marshalling used to represent sent packets */ protected int marshallingType; /** * Marshaller used to send packets */ private PacketMarshaller marshaller; /** * Indicates the need to compress sent data */ private boolean zipData=true; /** * Creates new client (connection from client to server) connection * @param host target host * @param port target port * @param id connection ID */ public Connection(String host, int port, int id) { this.host = host; this.port = port; this.id = id; setMarshallingType(DEFAULT_MARSHALLING); } /** * Creates new Server connection * @param socket accepted socket * @param id connection ID */ public Connection(Socket socket, int id) { this.socket = socket; this.id = id; setMarshallingType(DEFAULT_MARSHALLING); } /** * Returns <code>true</code> if it's the Server connection * @return <code>true</code> if it's the Server connection */ public boolean isServer() { return host == null; } /** * Returns the type of the marshalling used to send packets * @return the type of the marshalling used to send packets */ public int getMarshallingType() { return marshallingType; } /** * Sets the type of the marshalling used to send packets * @param marshallingType new marhalling type */ public void setMarshallingType(int marshallingType) { PacketMarshaller pm = marshallerFactory.getMarshaller(marshallingType); megamek.debug.Assert.assertTrue(pm != null, "Unknown marshalling type"); this.marshallingType = marshallingType; marshaller = pm; } /** * Opens the connection * @return <code>true</code> on success, <code>false</code> otherwise */ public synchronized boolean open() { if (!open) { if (socket == null) { try { socket = new Socket(host, port); } catch (Exception e) { return false; } } open = true; initThreads(); } return true; } /** * Closes the socket and shuts down the receiver and sender threads */ public void close() { synchronized (this) { System.err.print(getConnectionTypeAbbrevation()); sendQueue.reportContents(); sendQueue.finish(); receiver = null; sender = null; try { if (socket != null) { socket.close(); } } catch (IOException e) { System.err.print( "Error closing connection #" ); //$NON-NLS-1$ System.err.print( getId() ); System.err.print( ": " ); //$NON-NLS-1$ System.err.println( e.getMessage() ); // We don't need a full stack trace... we're // just closing the connection anyway. //e.printStackTrace(); } catch (NullPointerException ex) { //never initialized, poor thing } socket = null; } processConnectionEvent(new DisconnectedEvent(this)); } /** * Returns the connection ID * @return the connection ID */ public int getId() { return id; } /** * Sets the connection ID * @param id new connection ID * Be careful with this... */ public void setId(int id) { this.id = id; } public String getInetAddress() { if (socket != null) { return socket.getInetAddress().toString(); } return "Unknown"; } /** * Returns <code>true</code> if this connection compress the sent data * @return <code>true</code> if this connection compress the sent data */ public boolean isCompressed() { return zipData; } /** * Sets the compression * @param compress */ public void setCompression(boolean compress) { zipData = compress; } /** * Adds a packet to the send queue to be send on a seperate thread. */ public void send(Packet packet) { sendQueue.addPacket(new SendPacket(packet)); } /** * Send packet now; This is the blocking call. */ public synchronized void sendNow(SendPacket packet) { try { sendNetworkPacket(packet.getData(), packet.isCompressed()); debugLastFewCommandsSent.push(packet.getCommand()); } catch (Exception e) { e.printStackTrace(); } } /** * Returns <code>true</code> if there are pending packets * @return <code>true</code> if there are pending packets */ public boolean hasPending() { return sendQueue.hasPending(); } /** * Returns a very approximate count of how many bytes were sent * @return a very approximate count of how many bytes were sent */ public synchronized long bytesSent() { return bytesSent; } /** * Returns a very approximate count of how many bytes were received * @return a very approximate count of how many bytes were received */ public synchronized long bytesReceived() { return bytesReceived; } /** * Adds the specified connection listener to receive * connection events from connection. * * @param listener the connection listener. */ public void addConnectionListener(ConnectionListener listener) { connectionListeners.addElement(listener); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -