⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serverconnection.java

📁 ErGo是一个很早的Java通用围棋服务器(IGS/NNGS)客户端程序。有全部源码和文档
💻 JAVA
字号:
package ergo.server;

// $Id: ServerConnection.java,v 1.4 1999/08/29 02:40:40 sigue Exp $

/*
 *  Copyright (C) 1999  Carl L. Gay and Antranig M. Basman.
 *  See the file copyright.txt, distributed with this software,
 *  for further information.
 */

import ergo.GlobalOptions;
import ergo.ui.YNCDialog;
import ergo.ui.GoClient;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.awt.event.ActionListener;


/**
 * Maintains the connection to the server and provides line-oriented IO.
 *
 * @see SimpleServerConnection
 * @version $Revision: 1.4 $ - $Date: 1999/08/29 02:40:40 $
 */
public class ServerConnection implements Runnable, ActionListener, SimpleServerConnection {
  public GoClient client;
  public GoServer server;
  public Controller control;  // ---*** Get rid of this.
  private Socket sock;
  private BufferedReader netin;
  private PrintWriter netout;
  private boolean scanForLogin = true;
  private StringBuffer inputBuffer = new StringBuffer(150);
  private String previousLine;
  private Thread controllerThread = null;
  private Thread openConnThread = null;
  private YNCDialog openConnDialog = null;

  private ServerConnection () {}  // disallow default constructor

  public ServerConnection (GoClient client) {
    this.client = client;
  }

  // If created with a GoServer immediately open a conn to that server.
  /*
    hjs!  This is too dangerous. Starting a thread in a constructor,
    especially one that can invoke such complicated consequences,
    could start procedures that require the object that is being
    created, before it has time to finish creating itself

    ServerConnection (TerminalWindow term, GoServer server) {
      window = term;
      if (server != null)
        open(server);
    }
    */

  public String longName () { return server.name; }

  public String shortName () { return server.shortName(); }

  public String previousLine () { return previousLine; }

  // Try to open a connection to the server.
  // Return true if successful, else false.
  public boolean open (GoServer server) {
    if (isConnected()) {
      System.err.println("Attempt to connect to " + server.toString());
      System.err.println("  while already connected to "
			 + this.server.toString());
      return false;
    }
    else {
      this.server = server;
      openConnDialog = client.openYNCDialog("Connect", false,
				     "Connecting to " + server + "...",
				     null, null, "Cancel", this);
      openConnThread = new Thread(this);
      openConnThread.start();
      return true;
    }
  }

  // Implement Runnable interface so that the connection can be opened
  // in a separate thread.
  public void run () {
    openInternal();
  }

  public void openInternal () {
    try {
      sock = new Socket(server.name, server.port);
      // The second arg to this constructor, true, means to flush the
      // stream after a newline is sent.
      netout = new PrintWriter(sock.getOutputStream(), true);
      netin = new BufferedReader(new InputStreamReader(sock.getInputStream()));
      if (client != null)
	client.updateTitle();
      scanForLogin = true;

      // Create a Controller thread to read from this connection.
      // If the controller already exists, resume it.
      control = new Controller(this, client);
      controllerThread = new Thread(control, "Ergo Controller");
      controllerThread.start();
      client.noteConnected();
    } catch (UnknownHostException e) {
      client.displayString("Unknown host: " + server.name);
    } catch (IOException e) {
      client.displayString("Couldn't get I/O for the connection to: " +
			   server.name + " on port " + server.port);
    } finally {
      openConnThread = null;
      if (openConnDialog != null)  {
	  openConnDialog.close();
	  openConnDialog = null;
      }
    }
  }

  // Implement ActionListener so user can cancel the open operation.
  // The only possible action is to press the Cancel button, so if
  // this method is called just cancel the thread.
  public void actionPerformed (java.awt.event.ActionEvent e) {
    if (openConnThread != null)
      openConnThread.stop();
    openConnDialog = null;
  }

  public void close () {
    if (netin != null) {
      try {
	// Bug fix for Solaris exit. AMB 0.9
	if (controllerThread != null) {
	  controllerThread.stop();
	  controllerThread = null;
	}
        netin.close();
        netin = null;
        if (client != null) {
	  client.noteDisconnected();
	  client.displayString(">>> Ergo: Connection closed.");
	}
      }
      catch (IOException e) {
        System.err.println("Unable to close input connection to server.");
        System.err.println("Exiting anyway.");
      }
    }
    if (netout != null) {
      netout.close();
      netout = null;
    }
  }

  //
  // Implement the SimpleServerConnection interface
  //

  public boolean isConnected () {
    return (netin == null) ? false : true;
  }

  public boolean send (String command) {
    return send(command, true);
  }

  public boolean send (String command, boolean display) {
    if (!isConnected()) {
      return false;
    } else {
      if (display)
	client.displayCommand(command);
      netout.println(command);
      netout.flush();
      return true;
    }
  }

  private boolean bufferEquals (String s, int start) {
    for (int i = start; i < inputBuffer.length(); i++) {
      if (Character.toLowerCase(inputBuffer.charAt(i))
	  != Character.toLowerCase(s.charAt(i)))
        return false;
    }
    return true;
  }

  /*
   * Read a line of text from the server,  This has a bunch of extra hair
   * because it has to deal with the Login: and Password: prompts, which
   * are not followed immediately by a newline character, and the Login:
   * prompt is not preceded by the prompt message code (1);
   */
  public synchronized String readLine () throws IOException {
    inputBuffer.setLength(0);
    char last = 'a';      // a neutral value
    while(true) {
      int val = netin.read();
      if (val == -1) {    // -1 means end of stream encountered
        close();
        return inputBuffer.toString();
      }
      char ch = (char) val;
      if (ch == '\r') {
	if (last == '\r')  // On WING they sometimes send \r\r\n (!).
	  continue;        // Ignore multiple \r in a row.  Reasonable?
	netin.mark(2);
      }
      else if (ch == '\n') { 		     // this matches \n and \r\n
	break;
      }
      else
	inputBuffer.append(ch);

      if (last == '\r') {     // just plain \n w/o \r preceding.
	netin.reset();		     // unread the last char
	inputBuffer.setLength(inputBuffer.length() - 1);
	break;
      } else if (scanForLogin == true && ch == ':') {
        if (bufferEquals("Login:", 1))
	  break;
	else if (bufferEquals("Password:", 1)) {
	  break;
        }
      }
      last = ch;
    }
    previousLine = inputBuffer.toString();
    return previousLine;
  }


  public String toString () {
    return (isConnected() ? server.shortName() : "not connected");
  }


  public boolean scanningForLogin () {
    return scanForLogin;
  }

  public void stopScanningForLogin () {
    scanForLogin = false;
  }

}  // end class ServerConnection

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -