国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

僅用一個(gè)類的服務(wù)器

2019-11-18 14:56:48
字體:
供稿:網(wǎng)友

  作者:Greg Travis

<讓我們通過一個(gè)java程序的例子,學(xué)習(xí)建立一個(gè)簡單的TCP/ip服務(wù)器。大部分代碼都放在一個(gè)類中,這樣就很輕易入門->

本文介紹了快速實(shí)現(xiàn)一個(gè)簡單的TCP/IP服務(wù)器的技巧。核心代碼都在單個(gè)類Server.java中,所以很輕易建立和使用。

Server.java的結(jié)構(gòu)很簡單。它監(jiān)聽一個(gè)端口,對于每一個(gè)進(jìn)來的連接,生成處理該連接的線程。實(shí)際處理該連接的子程序并沒有實(shí)現(xiàn),所以你必須自己擴(kuò)展Server.java,寫個(gè)子程序來實(shí)現(xiàn)。

(這樣,從技術(shù)上講,這就不是“僅用一個(gè)類的服務(wù)器”,因?yàn)槟氵€需要用另外一個(gè)類,來完成某件事情。假如你真的堅(jiān)持打算只用一個(gè)類,只需把子類中的代碼放到Server.java中。)

下面的EchoServer.java的代碼體現(xiàn)了該程序的簡單性。EchoServer 完成如下的簡單功能:把客戶發(fā)來的信息再發(fā)回去。

-----------------------------------------------
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類的實(shí)現(xiàn)是很有趣的,因?yàn)樗鼘τ谒芯€程使用了一個(gè)Server類的實(shí)例。

Listener 線程
創(chuàng)建的第一個(gè)線程是“l(fā)istener”線程。該線程中的代碼對一個(gè)端口進(jìn)行監(jiān)聽,等待進(jìn)入的連接。一旦一個(gè)連接進(jìn)入時(shí),一個(gè)新的“connection”線程被創(chuàng)建,用于處理該連接。

Listener線程必須把用某種方法把新連接的Socket對象傳送給新線程。因?yàn)镴ava在創(chuàng)建線程時(shí),不具有傳遞參數(shù)的功能,所以使用了另外一個(gè)技術(shù):哈希表。

一個(gè)哈希表對象可以把線程對象映射為Socket對象。listener 線程創(chuàng)建了一個(gè)新的線程,然后把該新線程和新的socket放到哈希表中。當(dāng)新線程開始執(zhí)行時(shí),它從哈希表基于自己的線程對象中,通過調(diào)用Thread.currentThread(),讀入socket。

對于Listener線程來說,因?yàn)樗恍枰渌€程“傳遞”什么信息,此時(shí)的哈希表中就沒有Socket對象,這樣,程序就可以判定這是一個(gè)listener 線程而不是一個(gè)connection線程。

下面為Listener線程的代碼。現(xiàn)在的這個(gè)實(shí)現(xiàn)很簡單,因?yàn)樗÷粤艘恍┨幚怼S绕涫前l(fā)生例外時(shí)的處理,我沒有編寫這些代碼。因?yàn)檫@需要做更多的工作,而且依靠于具體的應(yīng)用。

-----------------------------------------------
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哈希表進(jìn)行整理,大家可以修改這個(gè)類,以便能夠完善這些工作,我把它們的代碼編寫工作作為練習(xí),留給讀者。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 玛多县| 奉节县| 新昌县| 石城县| 宁明县| 石景山区| 江门市| 若尔盖县| 西平县| 堆龙德庆县| 泽普县| 苍梧县| 长武县| 出国| 哈巴河县| 班玛县| 茶陵县| 安远县| 龙里县| 抚州市| 阳原县| 陕西省| 大荔县| 屏东市| 苗栗县| 明溪县| 田林县| 察雅县| 荥经县| 汉阴县| 淮阳县| 潞西市| 威信县| 松潘县| 农安县| 汤原县| 南雄市| 天全县| 瓮安县| 若尔盖县| 靖西县|