分享
 
 
 

仅用一个类的服务器

王朝other·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

作者:Greg Travis

<让我们通过一个Java程序的例子,学习建立一个简单的TCP/IP服务器。大部分代码都放在一个类中,这样就很轻易入门->

本文介绍了快速实现一个简单的TCP/IP服务器的技巧。核心代码都在单个类Server.java中,所以很轻易建立和使用。

Server.java的结构很简单。它监听一个端口,对于每一个进来的连接,生成处理该连接的线程。实际处理该连接的子程序并没有实现,所以你必须自己扩展Server.java,写个子程序来实现。

(这样,从技术上讲,这就不是“仅用一个类的服务器”,因为你还需要用另外一个类,来完成某件事情。假如你真的坚持打算只用一个类,只需把子类中的代码放到Server.java中。)

下面的EchoServer.java的代码体现了该程序的简单性。EchoServer 完成如下的简单功能:把客户发来的信息再发回去。

-----------------------------------------------

The One Class Server

-----------------------------------------------

EchoServer.java

-----------------------------------------------

-----------------------------------------------

import java.io.*;

import java.io.*;

public class EchoServer extends Server

{

// A single argument: the port on which to listen

public EchoServer( int port ) {

super( port );

}

// This function is called for each new connection; it

// implements whatever functionality is needed from the server.

// In this case, it simply sends back to the client all data

// that the client sends it. If it receives a ´q´, the

// whole server is shut down.

public void process( InputStream in, OutputStream out ) {

try {

while (true) {

int c = in.read();

if (c==´q´) {

close();

} else {

out.write( c );

}

}

} catch( IOException ie ) { System.out.println( ie ); }

}

// Command-line: "java EchoServer <port>"

static public void main( String args[] ) throws Exception {

int port = new Integer( args[0] ).intValue();

new EchoServer( port );

}

}

Server类的实现是很有趣的,因为它对于所有线程使用了一个Server类的实例。

Listener 线程

创建的第一个线程是“listener”线程。该线程中的代码对一个端口进行监听,等待进入的连接。一旦一个连接进入时,一个新的“connection”线程被创建,用于处理该连接。

Listener线程必须把用某种方法把新连接的Socket对象传送给新线程。因为Java在创建线程时,不具有传递参数的功能,所以使用了另外一个技术:哈希表。

一个哈希表对象可以把线程对象映射为Socket对象。listener 线程创建了一个新的线程,然后把该新线程和新的socket放到哈希表中。当新线程开始执行时,它从哈希表基于自己的线程对象中,通过调用Thread.currentThread(),读入socket。

对于Listener线程来说,因为它不需要其他线程“传递”什么信息,此时的哈希表中就没有Socket对象,这样,程序就可以判定这是一个listener 线程而不是一个connection线程。

下面为Listener线程的代码。现在的这个实现很简单,因为它省略了一些处理。尤其是发生例外时的处理,我没有编写这些代码。因为这需要做更多的工作,而且依靠于具体的应用。

-----------------------------------------------

The One Class Server

-----------------------------------------------

The Listener Thread

-----------------------------------------------

-----------------------------------------------

import java.io.*;

import java.net.*;

import java.util.*;

abstract public class Server implements Runnable

{

// The port the server will listen on

private int port;

// Used to "pass" a Socket to the new thread that will process it

private Hashtable handoff = new Hashtable();

// The first thread -- we store it here so we can kill it

// first when closing.

private Thread listener;

// A list of the Threads that have been started

private Vector threads = new Vector();

// A list of the Sockets that have connected to us

private Vector sockets = new Vector();

// The listen socket

private ServerSocket ss;

public Server( int port ) {

this.port = port;

// Start the listener thread. Because we haven´t passed a Socket

// object to this thread in the handoff table, it will know

// that it is to be the listener thread.

listener = new Thread( this );

listener.start();

}

synchronized public void close() {

// First, make sure there aren´t any incoming connections

listener.stop();

// Now, close all the sockets

for (Enumeration e = sockets.elements(); e.hasMoreElements();){

Socket s = (Socket)e.nextElement();

try {

s.close();

} catch( IOException ie ) { System.out.println( ie );}

}

// And stop all the threads

for (Enumeration e = threads.elements(); e.hasMoreElements();){

Thread t = (Thread)e.nextElement();

// But let´s not stop *ourselves* yet!

if (t != Thread.currentThread())

t.stop();

}

System.out.println( "Shutting down!" );

// Now we can stop ourselves.

Thread.currentThread().stop();

}

// This routine does the actual work of the server. It´s not

// implemented, so you have to extend this class to actually get

// something done.

abstract public void process( InputStream in, OutputStream out );

// This routine processes all the connections. All the threads

// started by this class run this same routine of the same instance

// of Server.

public void run() {

// Get the Socket that is being "passed" to us by the listener

// thread. If there is no Socket here for us, then we ARE the

// listener thread, or at least we are about to be.

Socket s = (Socket)handoff.get( Thread.currentThread() );

if (s==null) {

// Aha -- we are the very first thread, the listener thread.

// Start listening.

try {

// Set up the listen socket.

ss = new ServerSocket( port );

System.out.println( "Listening on "+port );

while (true) {

// Accept a new connection

s = ss.accept();

synchronized( this ) {

System.out.println( "Connection from "+s.getInetAddress() );

// Make a new thread to handle this connection

Thread t = new Thread( this );

// Store the thread and socket in the lists

sockets.addElement( s );

threads.addElement( t );

// The Socket object is "passed" to the new thread by

// getting stuffed here. When the new thread is started,

// it will pull the Socket object out of here based on

// its own Thread object.

handoff.put( t, s );

// All set! Start the thread!

t.start();

}

}

} catch( IOException ie ) {}

} else {

// We are a processing socket.

try {

InputStream in = s.getInputStream();

OutputStream out = s.getOutputStream();

// Call the actually-do-something routine in the subclass of

// this object, so that something can actually get done.

process( in, out );

} catch( IOException ie ) { System.out.println( ie ); }

}

}

}

此处,我们也没有对socket,线程列表以及对handoff哈希表进行整理,大家可以修改这个类,以便能够完善这些工作,我把它们的代码编写工作作为练习,留给读者。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有