帐前卒专栏

code, software architect, articles and novels.
代码,软件架构,博客和小说

vc++中的多线程编程:


HANDLE hMutex; // Create a mutex with no initial owner. 必须要创建一个句柄

hMutex = CreateMutex( NULL, // no security attributes

FALSE, // initially not owned
"
MutexToProtectDatabase " ); // name of mutex
//
这个句柄只想信号量,第一个参数一半为NULL,第二个(初始化时是否被获得)false为现在可以被任何人使用
//
第三个参数是为信号量起名,方便以后查找该信号量
if
(hMutex == NULL)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
ContractedBlock.gif) … {

// Check for error.一般不必这样用。
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kEnd.gif) }


BOOL FunctionToWriteToDatabase(HANDLE hMutex)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
ContractedBlock.gif) … {

DWORD dwWaitResult; // Request ownership of mutex.

dwWaitResult = WaitForSingleObject(

hMutex, // handle to mutex

5000L ); // five-second time-out interval
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) switch (dwWaitResult) … {

// The thread got mutex ownership.

case WAIT_OBJECT_0:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) __try … {

// Write to the database.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) __finally … {

// Release ownership of the mutex object.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) if ( ! ReleaseMutex(hMutex)) … {

// Deal with error.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) break ; }

// Cannot get mutex ownership due to time-out.

case WAIT_TIMEOUT:

return FALSE;

// Got ownership of the abandoned mutex object.

case WAIT_ABANDONED:

return FALSE;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

return TRUE;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kEnd.gif) }

DWORD dwWaitResult 只是为了判断信号量的归谁所有。 WaitForSingleObject() 相当与P()操作,参数有两个:第一个是
信号量,第二个是等待时间。INFINITE代表无限等待。5000L代表等待5秒,如果5秒内获得信号量,dwWaitResult==
WAIT_OBJECT_0,如果5秒没有得到信号量,则dwWaitResult== WAIT_TIMEOUT,而
WAIT_ABANDONED代表操作失败。 ReleaseMutex(hMutex)相当于V()操作。参数为信号量。

如果希望在一个函数中启动线程并调用该函数,应该这样写代码

void reading(void* name);这个函数一定要是void的返回类型。然后可以在调用函数中这样写:

_beginthread(&reading,0,(void*)english); 其中第一参数是要调用函数的函数指针。第二个函数是线程优先级一般为0。第三个
参数是个void指针,一般用来传函数的参数。如果想传多个参数只要把那个指针指向一个结构体就可以。到函数那里再转换为相应的结构体指针就可以了。

Sleep(5000L);这个函数一般是用来让线程睡眠的。参数是unsigned long,现在是睡5秒。
这只是多线程的编程常用到的几个函数。对于多线程编程还要注意同步和死锁,在这篇文字就不讨论了。

用Eclipse3.1 + Myeclipse4.0 + Tomcat5.0 + j2sdk1.5
搭建J2EE开发环境(转自http://hdfyq.diy.myrice.com/)

一、安装j2sdk1.5,设定环境变量。

我的安装目录是 ** D:/j2sdk ** 。 所以设定环境变量如下:

操作: My Computer(右键) ----> Properties ----> Advanced ----> Environment
Variables :

设定环境变量为:
1. (新建)JAVA_HOME: D:/j2sdk
2. (新建)CLASSPATH: .;D:/j2sdk/lib/dt.jar;D:/j2sdk/lib/tools.jar
(注意:点号不能省略,表示当前目录)
3. 编辑PATH的变量值,在后面加上 ;%JAVA_HOME%/bin (注意:要有分号隔开)
到这里,j2sdk安装完毕,用命令简单测试一下: java -version

二、安装Tomcat5.0

去下载一个Tomcat的zip版, 我用的是 jakarta-tomcat-5.0.28.zip , 不下安装版的目的是可以使用多个Tomcat。

直接解压缩到 G 盘:

三、安装Eclipse3.1

下载地址: http://www.eclipse.org/downloads/index.php
找到下面的页面:

找个亚洲的服务器下载,速度会快一点。在flashget中如下:

直接解压缩就可以用了,我是解压缩在 G 盘:

到这里, Eclipse3.1 安装完毕。

四、安装 Myeclipse4.0 (myeclipse不是免费的,所以我们先下载一个试用版,再去网上下载一个注册机)

下载版本: MyEclipse Enterprise Workbench 4.0 GA for Windows 98/2000/XP (8/29/2005)
如下图:

在flashget下载中显示如下:

下载完成后,开始安装:

1. 选择你的eclipse所在目录,其它都点下一步,默认安装。

2.安装完毕之后,找到myeclipse的安装目录, 如下图所示:

3. 将features和plugins这2个目录复制出来。这样做的目的是为了在一台电脑上可以使用多个独立的eclipse开发平台。如下图所示:

4. 将刚才安装的 myeclipse 删除(反安装)。

5. 将第3步复制的features和plugins这2个目录, 覆盖到 G

解释一下上面做的原因: 因为myeclipse是eclipse的插件,所以只要把features和plugins这2个目录覆盖在eclipse的相应目录,e
clipse会自动认出这些插件。

到这一步,myeclipse算是安装完毕。 G 盘目录如下:

五、破解myeclipse4.0

1.去google搜索下载一个注册机。如下图:

2. 输入名字,算号,如下图:

3.运行eclipse.exe, 设定同目录下的workspace, 如下图:

4.myeclipse插件已经被自动认出,如下图:

5. 点击 Window ----> Preferences ----> Subscription ----> Enter Subscription,
输入注册码,破解myeclipse,下图:

到这里,myeclipse破解完毕。

六、设定myeclipse的 jdk 和 tomcat 服务器。

1. 增加一个jre, 点击 Window ----> Preferences ----> Installed JREs ----> Add
如下图:(找到自己的j2sdk安装目录)

2. 指定Tomcat服务器,Window ----> Preferences ----> Tomcat5,
并设定该tomcat所用的jre为我们上一步新增的。如下面2个图:

到这一步,我们的开发环境就搭建完毕了。

七、新建一个项目来试一试?

1. 点击 File ----> New ----> Project , 选择Web Project, 再点下一步, 如下图:

2. 在 Project Name 中输入test, 点 finish。 如下图:

3. 开发工具自动生成了test项目。 如下图:

4.点击 WebRoot ----> (右键)New ----> JSP , 新建一个 JSP 页面 (hello.jsp), 如下图:

5. 编辑器生成的是jsp文件是按模板生成的, 简单修改一下, 代码如下图:

6. 再用同样的方法, 新建一个叫 hello_result.jsp 的JSP文件, 代码如下图:

7. deploy(部署)这个test项目。 如下图: (用黑线画了的按钮就是 deploy 的按钮) , 在弹出窗口点 Add, 部署test项目。

8. 启动Tomcat服务器。如下图: (用黑线画了的按钮就是 启动Tomcat 的按钮)

9. Tomcat 启动输出信息如下图:

10. 网页访问和结果图.

大家可以去eclipse的workspace目录下看看test项目的代码,也可以去Tomcat的webapps目录下,看看部署之后的 test项目的结构。

RSA 算法:
其中加密encode和解密decode中的效率可以提高的log(n)

但是这个算法只是原型,只能对数字加密,对字符串加密时要将转换成AScII码的东东进行拆分才可以。要按位加密。当q,p过大时,将有溢出。改进的可以自己写一个大
数类。但没有时间了,暂时就做成这个样子吧。


#include < iostream >

#include < string >

#include < ctime >

#include " math.h "

using namespace std;


bool isPrime( long ); // the number is prime and return true, else return
false;

long gcd( long a, long b); // find a number which the two number a and
b divide exactly.

long publicKey( long p, long q); // using p, q to calculate the public
key e.

long privateKey( long e, long Qn); // using e ,Qn to calculate the
private key d.

long generKey( const long p, const long q, long * pubKey, long *
priKey); // get the public key and private key. And return n = pq.
//
char
 encode(char *,long n,long pubKey); // encode the Text
//
char * decode(char *,long n,long priKey); // decode the Text which has been
encoded.

long encode( long , long n, long pubKey); // encode the Text

long decode( long , long n, long priKey); // decode the Text which
has been encoded.

int main()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
ContractedBlock.gif) … {


long p,q;

long pubKey ;

long priKey ;

bool pass = true ;

while (pass)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {

cout << " input two prime numbers! and the two numbers are bigger than two
!! " << endl;

cin >> p >> q;

// srand(time(0));

// q = rand();

// p = rand();

if (isPrime(p) && isPrime(q))

pass = false ;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

cout << " p = " << p << " q = " << q << endl;

long n = generKey(p,q, & pubKey, & priKey);

cout << " n: " << n << endl;

cout << " input the number for encoding! " << endl;

long num;

cin >> num;

// cout << decode(encode(txt,n,pubKey),n,priKey);

long enText = encode(num,n,pubKey);

cout << " encode the Text: " << enText << endl;

cout << " decode the Text: " << decode(enText,n,priKey) << endl;

return 0 ;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kEnd.gif) }


bool isPrime( long a)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
ContractedBlock.gif) … {

if (a > 2 )
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {

int b = 2 ,c = sqrt(a);

for (; b < c; b ++ )
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {

if (a % b == 0 )

return false ;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

return true ;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

return false ;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kEnd.gif) }


long gcd( long a, long b)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
ContractedBlock.gif) … {

int x = a % b;

if (x == 0 )

return b;

else

return gcd(b,x);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kEnd.gif) }


long publicKey( const long p, const long q, const long Qn)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
ContractedBlock.gif) … {


srand(time( 0 ));

long e = rand();

if (e >= Qn)

e = 3 ;

while (gcd(e,Qn) != 1 )
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {


e ++ ;

if (e >= Qn)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {

e = 3 ;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

cout << " e: " << e << endl;

return e;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kEnd.gif) }


long privateKey( const long e, const long Qn)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
ContractedBlock.gif) … {

srand(time( 0 ));

long d = rand();

if (d >= Qn)

d = 3 ;

while (e * d % Qn != 1 || e == d)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {

d ++ ;

if (d >= Qn)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {

d = 3 ;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

cout << " d: " << d << endl;

return d;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kEnd.gif) }


long generKey( const long p, const long q, long * pubKey, long *
priKey)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
ContractedBlock.gif) … {

long n = p * q;

long Qn = (p - 1 ) * (q - 1 );

  • pubKey = publicKey(p,q,Qn);
  • priKey = privateKey( * pubKey,Qn);

    return n;
    ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
    kEnd.gif) }



    ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
    kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
    ContractedBlock.gif) /**/ /*


    char * encode(char * txt,long n,long pubKey)

    {

    int length = strlen(txt);

    char* text = new char[length];

    strcpy(text,txt);

    for(int i = 0; i < length; i++)

    {


    text[i] =(int) pow(text[i],pubKey) % n;

    }

    return text;

    }


    char * decode(char * txt,long n,long priKey)

    {

    int length = strlen(txt);

    char* text = new char[length];

    strcpy(text,txt);

    for(int i = 0; i < length; i++)

    {

    text[i] = (int)pow(text[i],priKey) % n;

    }

    return text;

    }
    ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
    kEnd.gif) */

    long encode( long num, long n, long pubKey)
    ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
    kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
    ContractedBlock.gif) … {

    long tmp = 1 ;

    for ( int i = 0 ; i < pubKey; i ++ )
    ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
    lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
    rs/ContractedSubBlock.gif) … {

    tmp *= num ;

    tmp %= n;
    ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
    lockEnd.gif) }

    return tmp;
    ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
    kEnd.gif) }

    long decode( long num, long n, long priKey)
    ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
    kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
    ContractedBlock.gif) … {

    long tmp = 1 ;

    for ( int i = 0 ; i < priKey; i ++ )
    ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
    lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
    rs/ContractedSubBlock.gif) … {

    tmp *= num ;

    tmp %= n;
    ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
    lockEnd.gif) }

    return tmp;
    ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
    kEnd.gif) }

当初成立编辑部,后来发现人员倒是招缆了一批。经过培训感觉还是可以的。

下学期面临换届,感觉应该留下来什么方针政策。否则就失去了创建此部的目的。新一届要走的路应该是:

宣传,招新,培训,任留。

宣传将为招新做铺垫。招的新人估计也没有什么高人。那就要进行多次培训。培训中做几个小点的项目。每个人的表现如何领导者都一一在目。然后就是下届将由谁来领导。表现
好的将留在本部。差的就说byebye。尽量多的挽留培训出来的人,这样对下一届的编辑部也有好处。这些被培训出来的人可以留在下届继续培训新人。这样编辑部的工作才
会有延续性。

这4步中的重中之重在于培训。培训的好坏将对下届产生深远的影响。当然管理者要知人用人。对部下充分的信任这是必要的。否则谁为你买命的干活?

想来编辑部也算得上学生会中管理的较好的部门。人多手杂也相当不好管理。而且没有自己的办公室。啥时候也向院里要一间。这要算是历史遗留问题了。留给下届解决好了。还
有办纸制院刊的问题也要留给下届了。希望能打消上级的那些念头。

看下面的这段代码,摘自《Java Examples in a Nutsbell》(java实例技术手册):

就是一个简单的通用的多线程服务器

这个例子可以通过配置参数:

1
java je3.net.Server -control www 3333 je3.net.Server$HTTPMirror 5555

来启动,然后再ie中输入: http://localhost:5555 就可以看到效果。

写一个policy文件放在同根目录下:叫server.policy

grant{
permission java.net.SocketPermission “*:1024-4444”,“connect,accept”;
permission java.io.FilePermission “E://workspace//j2ee1.3//-”, “read”;
};

下面加上jvm虚拟机参数

java -Djava.security.manager -Djava.security.policy=server.policy

je3.net.Server -control www 3333 je3.net.Server$HTTPMirror 5555再次启动。

按道理,本不应该启动。因为端口5555并没有得到连接许可。但是很可惜输入 http://localhost:5555
还是可以看到结果。因为在java的sdk中暗含了java.policy文件。那就把它改为-
Djava.security.policy==server.policy应该就可以了。结果跑不了了。原因就在policy文件中的permission
java.net.SocketPermission “:1024-4444",“connect,accept”; 其实,我一直不太清楚listen
,accept,connect的区别在什么地方。但是这里的例子说明你只用permission java.net.SocketPermission "
:10
24-4444”,“listen”;就可以了。端口该闭的就闭了。如果用accept和connect反而没有什么用。不知道java的安全性高在什么地方。因为j
ava.policy文件中从1024以上的端口全都使用了listen。所以以后要配置端口时一定要注意。

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
ContractedBlock.gif) // /*

* Copyright © 2004 David Flanagan.  All rights reserved.

* This code is from the book Java Examples in a Nutshell, 3nd Edition.

* It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.

* You may study, use, and modify it for any non-commercial purpose,

* including teaching and use in open-source projects.

* You may distribute it non-commercially as long as you retain this notice.

* For a commercial use license, or to purchase the book,

* please visit http://www.davidflanagan.com/javaexamples3.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kEnd.gif) /

package je3.net;

import java.io. * ;

import java.net. * ;

import java.util. * ;

import java.util.logging. * ;

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
ContractedBlock.gif) /
 / /


* This class is a generic framework for a flexible, multi-threaded server.

* It listens on any number of specified ports, and, when it receives a

* connection on a port, passes input and output streams to a specified Service

* object which provides the actual service.  It can limit the number of

* concurrent connections, and logs activity to a specified stream.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
ContractedBlock.gif) public class Server … {
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* A main() method for running the server as a standalone program.  The

* command-line arguments to the program should be pairs of servicenames

* and port numbers.  For each pair, the program will dynamically load the

* named Service class, instantiate it, and tell the server to provide

* that Service on the specified port.  The special -control argument

* should be followed by a password and port, and will start special

* server control service running on the specified port, protected by the

* specified password.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public static void main(String[] args) … {
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) try … {

if (args.length < 2 ) // Check number of arguments

throw new IllegalArgumentException( " Must specify a service " );


// Create a server object that has a limit of 10 concurrent

// connections, and logs to a Logger at the Level.INFO level

// Prior to Java 1.4 we did this: new Server(System.out, 10);

Server s = new Server(Logger.getLogger(Server. class .getName()),

Level.INFO, 10 );


// Parse the argument list

int i = 0 ;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) while (i < args.length) … {
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) if (args[i].equals( " -control " )) … {
// Handle the -control arg

i ++ ;

String password = args[i ++ ];

int port = Integer.parseInt(args[i ++ ]);

// add control service

s.addService( new Control(s, password), port);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) else … {

// Otherwise start a named service on the specified port.

// Dynamically load and instantiate a Service class

String serviceName = args[i ++ ];

Class serviceClass = Class.forName(serviceName);

Service service = (Service)serviceClass.newInstance();

int port = Integer.parseInt(args[i ++ ]);

s.addService(service, port);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) catch (Exception e) … { // Display a message
if anything goes wrong

System.err.println( " Server: " + e);

System.err.println( " Usage: java Server " +

" [-control  ] " +

" [  … ] " );

System.exit( 1 );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }


// This is the state for the server

Map services; // Hashtable mapping ports to Listeners

Set connections; // The set of current connections

int maxConnections; // The concurrent connection limit

ThreadGroup threadGroup; // The threadgroup for all our threads


// This class was originally written to send logging output to a stream.

// It has been retrofitted to also support the java.util.logging API of

// Java 1.4.  You can use either, neither, or both.

PrintWriter logStream; // Where we send our logging output to

Logger logger; // A Java 1.4 logging destination

Level logLevel; // the level to log messages at

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This is the Server() constructor.  It must be passed a stream

* to send log output to (may be null), and the limit on the number of

* concurrent connections.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public Server(OutputStream logStream, int
maxConnections) … {

this (maxConnections);

setLogStream(logStream);

log( " Starting server " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This constructor added to support logging with the Java 1.4 Logger class
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public Server(Logger logger, Level logLevel, int
maxConnections) … {

this (maxConnections);

setLogger(logger, logLevel);

log( " Starting server " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This constructor supports no logging
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public Server( int maxConnections) … {

threadGroup = new ThreadGroup(Server. class .getName());

this .maxConnections = maxConnections;

services = new HashMap();

connections = new HashSet(maxConnections);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* A public method to set the current logging stream.  Pass null

* to turn logging off.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public synchronized void
setLogStream(OutputStream out) … {

if (out != null ) logStream = new PrintWriter(out);

else logStream = null ;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* Set the current Logger and logging level. Pass null to turn logging off.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public synchronized void setLogger(Logger
logger, Level level) … {

this .logger = logger;

this .logLevel = level;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /* Write the specified string to the log
/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) protected synchronized void log(String s) …
{

if (logger != null ) logger.log(logLevel, s);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) if (logStream != null ) … {

logStream.println( " [ " + new Date() + " ] " + s);

logStream.flush();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /* Write the specified object to the log
/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) protected void log(Object o) … {
log(o.toString()); }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This method makes the server start providing a new service.

* It runs the specified Service object on the specified port.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /

public synchronized void addService(Service service, int port)

throws IOException
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {

Integer key = new Integer(port); // the hashtable key

// Check whether a service is already on that port

if (services.get(key) != null )

throw new IllegalArgumentException( " Port " + port +

" already in use. " );

// Create a Listener object to listen for connections on the port

Listener listener = new Listener(threadGroup, port, service);

// Store it in the hashtable

services.put(key, listener);

// Log it

log( " Starting service " + service.getClass().getName() +

" on port " + port);

// Start the listener running.

listener.start();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This method makes the server stop providing a service on a port.

* It does not terminate any pending connections to that service, merely

* causes the server to stop accepting new connections
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public synchronized void removeService( int
port) … {

Integer key = new Integer(port); // hashtable key

// Look up the Listener object for the port in the hashtable

final Listener listener = (Listener) services.get(key);

if (listener == null ) return ;

// Ask the listener to stop

listener.pleaseStop();

// Remove it from the hashtable

services.remove(key);

// And log it.

log( " Stopping service " + listener.service.getClass().getName() +

" on port " + port);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This nested Thread subclass is a “listener”.  It listens for

* connections on a specified port (using a ServerSocket) and when it gets

* a connection request, it calls the servers addConnection() method to

* accept (or reject) the connection.  There is one Listener for each

* Service being provided by the Server.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public class Listener extends Thread … {

ServerSocket listen_socket; // The socket to listen for connections

int port; // The port we’re listening on

Service service; // The service to provide on that port

volatile boolean stop = false ; // Whether we’ve been asked to stop

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* The Listener constructor creates a thread for itself in the

* threadgroup.  It creates a ServerSocket to listen for connections

* on the specified port.  It arranges for the ServerSocket to be

* interruptible, so that services can be removed from the server.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /

public Listener(ThreadGroup group, int port, Service service)

throws IOException
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {

super (group, " Listener: " + port);

listen_socket = new ServerSocket(port);

// give it a non-zero timeout so accept() can be interrupted

listen_socket.setSoTimeout( 5000 );

this .port = port;

this .service = service;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This is the polite way to get a Listener to stop accepting

* connections
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) ** /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public void pleaseStop() … {

this .stop = true ; // Set the stop flag

this .interrupt(); // Stop blocking in accept()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) try … { listen_socket.close(); } // Stop
listening.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) catch (IOException e) … {}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* A Listener is a Thread, and this is its body.

* Wait for connection requests, accept them, and pass the socket on

* to the addConnection method of the server.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public void run() … {
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) while ( ! stop) … { // loop until we’re
asked to stop.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) try … {

Socket client = listen_socket.accept();

addConnection(client, service);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) catch (InterruptedIOException e) … {}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) catch (IOException e) … {log(e);}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This is the method that Listener objects call when they accept a

* connection from a client.  It either creates a Connection object

* for the connection and adds it to the list of current connections,

* or, if the limit on connections has been reached, it closes the

* connection.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) protected synchronized void addConnection(Socket
s, Service service) … {

// If the connection limit has been reached
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) if (connections.size() >= maxConnections) …
{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) try … {

// Then tell the client it is being rejected.

PrintWriter out = new PrintWriter(s.getOutputStream());

out.print( " Connection refused; " +

" the server is busy; please try again later. " );

out.flush();

// And close the connection to the rejected client.

s.close();

// And log it, of course

log( " Connection refused to " +

s.getInetAddress().getHostAddress() +

" : " + s.getPort() + " : max connections reached. " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) } catch (IOException e) … {log(e);}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) else … { // Otherwise, if the limit has not
been reached

// Create a Connection thread to handle this connection

Connection c = new Connection(s, service);

// Add it to the list of current connections

connections.add©;

// Log this new connection

log( " Connected to " + s.getInetAddress().getHostAddress() +

" : " + s.getPort() + " on port " + s.getLocalPort() +

" for service " + service.getClass().getName());

// And start the Connection thread to provide the service

c.start();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* A Connection thread calls this method just before it exits.  It removes

* the specified Connection from the set of connections.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) protected synchronized void
endConnection(Connection c) … {

connections.remove©;

log( " Connection to " + c.client.getInetAddress().getHostAddress() +

" : " + c.client.getPort() + " closed. " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /* Change the current connection limit
/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public synchronized void setMaxConnections( int
max) … {

maxConnections = max;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This method displays status information about the server on the

* specified stream.  It can be used for debugging, and is used by the

* Control service later in this example.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public synchronized void
displayStatus(PrintWriter out) … {

// Display a list of all Services that are being provided

Iterator keys = services.keySet().iterator();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) while (keys.hasNext()) … {

Integer port = (Integer) keys.next();

Listener listener = (Listener) services.get(port);

out.print( " SERVICE " + listener.service.getClass().getName()

+ " ON PORT " + port + " " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }


// Display the current connection limit

out.print( " MAX CONNECTIONS: " + maxConnections + " " );


// Display a list of all current connections

Iterator conns = connections.iterator();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) while (conns.hasNext()) … {

Connection c = (Connection)conns.next();

out.print( " CONNECTED TO " +

c.client.getInetAddress().getHostAddress() +

" : " + c.client.getPort() + " ON PORT " +

c.client.getLocalPort() + " FOR SERVICE " +

c.service.getClass().getName() + " " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This class is a subclass of Thread that handles an individual

* connection between a client and a Service provided by this server.

* Because each such connection has a thread of its own, each Service can

* have multiple connections pending at once.  Despite all the other

* threads in use, this is the key feature that makes this a

* multi-threaded server implementation.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public class Connection extends Thread … {

Socket client; // The socket to talk to the client through

Service service; // The service being provided to that client

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This constructor just saves some state and calls the superclass

* constructor to create a thread to handle the connection.  Connection

* objects are created by Listener threads.  These threads are part of

* the server’s ThreadGroup, so all Connection threads are part of that

* group, too.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public Connection(Socket client, Service service)
… {

super ( " Server.Connection: " +

client.getInetAddress().getHostAddress() +

" : " + client.getPort());

this .client = client;

this .service = service;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This is the body of each and every Connection thread.

* All it does is pass the client input and output streams to the

* serve() method of the specified Service object.  That method is

* responsible for reading from and writing to those streams to

* provide the actual service.  Recall that the Service object has

* been passed from the Server.addService() method to a Listener

* object to the addConnection() method to this Connection object, and

* is now finally being used to provide the service.  Note that just

* before this thread exits it always calls the endConnection() method

* to remove itself from the set of connections
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public void run() … {
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) try … {

InputStream in = client.getInputStream();

OutputStream out = client.getOutputStream();

service.serve(in, out);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) catch (IOException e) … {log(e);}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) finally … { endConnection( this ); }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* Here is the Service interface that we have seen so much of.  It defines

* only a single method which is invoked to provide the service.  serve()

* will be passed an input stream and an output stream to the client.  It

* should do whatever it wants with them, and should close them before

* returning.

*

* All connections through the same port to this service share a single

* Service object.  Thus, any state local to an individual connection must

* be stored in local variables within the serve() method.  State that

* should be global to all connections on the same port should be stored

* in instance variables of the Service class.  If the same Service is

* running on more than one port, there will typically be different

* Service instances for each port.  Data that should be global to all

* connections on any port should be stored in static variables.

*

* Note that implementations of this interface must have a no-argument

* constructor if they are to be dynamically instantiated by the main()

* method of the Server class.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public interface Service … {

public void serve(InputStream in, OutputStream out) throws IOException;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* A very simple service.  It displays the current time on the server

* to the client, and closes the connection.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public static class Time implements Service
… {
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public void serve(InputStream i, OutputStream o)
throws IOException … {

PrintWriter out = new PrintWriter(o);

out.print( new Date() + " " );

out.close();

i.close();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This is another example service.  It reads lines of input from the

* client, and sends them back, reversed.  It also displays a welcome

* message and instructions, and closes the connection when the user

* enters a ‘.’ on a line by itself.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public static class Reverse implements Service
… {
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public void serve(InputStream i, OutputStream o)
throws IOException … {

BufferedReader in = new BufferedReader( new InputStreamReader(i));

PrintWriter out =

new PrintWriter( new BufferedWriter( new OutputStreamWriter(o)));

out.print( " Welcome to the line reversal server. " );

out.print( " Enter lines.  End with a ‘.’ on a line by itself. " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) for (;😉 … {

out.print( " > " );

out.flush();

String line = in.readLine();

if ((line == null ) || line.equals( " . " )) break ;

for ( int j = line.length() - 1 ; j >= 0 ; j -- )

out.print(line.charAt(j));

out.print( " " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

out.close();

in.close();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This service is an HTTP mirror, just like the HttpMirror class

* implemented earlier in this chapter.  It echos back the client’s

* HTTP request
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public static class HTTPMirror implements
Service … {
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public void serve(InputStream i, OutputStream o)
throws IOException … {

BufferedReader in = new BufferedReader( new InputStreamReader(i));

PrintWriter out = new PrintWriter(o);

out.print( " HTTP/1.0 200 " );

out.print( " Content-Type: text/plain " );

String line;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) while ((line = in.readLine()) != null ) …
{

if (line.length() == 0 ) break ;

out.print(line + " " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

out.close();

in.close();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This service demonstrates how to maintain state across connections by

* saving it in instance variables and using synchronized access to those

* variables.  It maintains a count of how many clients have connected and

* tells each client what number it is
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public static class UniqueID implements
Service … {

public int id = 0 ;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public synchronized int nextId() … { return
id ++ ; }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public void serve(InputStream i, OutputStream o)
throws IOException … {

PrintWriter out = new PrintWriter(o);

out.print( " You are client #: " + nextId() + " " );

out.close();

i.close();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This is a non-trivial service.  It implements a command-based protocol

* that gives password-protected runtime control over the operation of the

* server.  See the main() method of the Server class to see how this

* service is started.

*

* The recognized commands are:

*   password: give password; authorization is required for most commands

*   add:      dynamically add a named service on a specified port

*   remove:   dynamically remove the service running on a specified port

*   max:      change the current maximum connection limit.

*   status:   display current services, connections, and connection limit

*   help:     display a help message

*   quit:     disconnect

*

* This service displays a prompt, and sends all of its output to the user

* in capital letters.  Only one client is allowed to connect to this

* service at a time.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public static class Control implements Service
… {

Server server; // The server we control

String password; // The password we require

boolean connected = false ; // Whether a client is already connected

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* Create a new Control service.  It will control the specified Server

* object, and will require the specified password for authorization

* Note that this Service does not have a no argument constructor,

* which means that it cannot be dynamically instantiated and added as

* the other, generic services above can be.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public Control(Server server, String password)
… {

this .server = server;

this .password = password;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This is the serve method that provides the service.  It reads a

* line the client, and uses java.util.StringTokenizer to parse it

* into commands and arguments.  It does various things depending on

* the command.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * */
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public void serve(InputStream i, OutputStream o)
throws IOException … {

// Setup the streams

BufferedReader in = new BufferedReader( new InputStreamReader(i));

PrintWriter out = new PrintWriter(o);

String line; // For reading client input lines

// Has the user has given the password yet?

boolean authorized = false ;


// If there is already a client connected to this service, display

// a message to this client and close the connection.  We use a

// synchronized block to prevent a race condition.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) synchronized ( this ) … {
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) if (connected) … {

out.print( " ONLY ONE CONTROL CONNECTION ALLOWED. " );

out.close();

return ;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

else connected = true ;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }


// This is the main loop: read a command, parse it, and handle it
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) for (;😉 … { // infinite loop

out.print( " > " ); // Display a prompt

out.flush(); // Make it appear right away

line = in.readLine(); // Get the user’s input

if (line == null ) break ; // Quit if we get EOF.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) try … {

// Use a StringTokenizer to parse the user’s command

StringTokenizer t = new StringTokenizer(line);

if ( ! t.hasMoreTokens()) continue ; // if input was empty

// Get first word of the input and convert to lower case

String command = t.nextToken().toLowerCase();

// Now compare to each of the possible commands, doing the

// appropriate thing for each command
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) if (command.equals( " password " )) … {
// Password command

String p = t.nextToken(); // Get the next word
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) if (p.equals( this .password)) … { // Is
it the password?

out.print( " OK " ); // Say so

authorized = true ; // Grant authorization
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

else out.print( " INVALID PASSWORD " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) else if (command.equals( " add " )) … {
// Add Service command

// Check whether password has been given

if ( ! authorized) out.print( " PASSWORD REQUIRED " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) else … {

// Get the name of the service and try to

// dynamically load and instantiate it.

// Exceptions will be handled below

String serviceName = t.nextToken();

Class serviceClass = Class.forName(serviceName);

Service service;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) try … {

service = (Service)serviceClass.newInstance();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) catch (NoSuchMethodError e) … {

throw new IllegalArgumentException(

" Service must have a " +

" no-argument constructor " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

int port = Integer.parseInt(t.nextToken());

// If no exceptions occurred, add the service

server.addService(service, port);

out.print( " SERVICE ADDED " ); // acknowledge
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) else if (command.equals( " remove " )) …
{ // Remove service

if ( ! authorized) out.print( " PASSWORD REQUIRED " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) else … {

int port = Integer.parseInt(t.nextToken());

server.removeService(port); // remove the service

out.print( " SERVICE REMOVED " ); // acknowledge
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) else if (command.equals( " max " )) … {
// Set connection limit

if ( ! authorized) out.print( " PASSWORD REQUIRED " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) else … {

int max = Integer.parseInt(t.nextToken());

server.setMaxConnections(max);

out.print( " MAX CONNECTIONS CHANGED " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) else if (command.equals( " status " )) …
{ // Status Display

if ( ! authorized) out.print( " PASSWORD REQUIRED " );

else server.displayStatus(out);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) else if (command.equals( " help " )) … {
// Help command

// Display command syntax.  Password not required

out.print( " COMMANDS: " +

" password  " +

" add   " +

" remove  " +

" max  " +

" status " +

" help " +

" quit " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

else if (command.equals( " quit " )) break ; // Quit command.

else out.print( " UNRECOGNIZED COMMAND " ); // Error
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) catch (Exception e) … {

// If an exception occurred during the command, print an

// error message, then output details of the exception.

out.print( " ERROR WHILE PARSING OR EXECUTING COMMAND: " +

e + " " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

// Finally, when the loop command loop ends, close the streams

// and set our connected flag to false so that other clients can

// now connect.

connected = false ;

out.close();

in.close();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kEnd.gif) }

一般来说equals()方法是比较两个对象值的。

例如比较两个Integer对象

1
2
3
4
5
6
7
8
public  class  Equalival  {  

public static void main(String[] args) {
Integer n1 = new Integer( 47 );
Integer n2 = new Integer( 47 );
System.out.println(n1.equals(n2));
}
}

打印

1
true

//Thinking in Java中的例子

==操作符是用来比较引用是否相等

1
2
3
4
5
6
7
8
9
10

public class Equalival {
public static void main(String[] args) {
Integer n1 = new Integer( 47 );
Integer n2 = new Integer( 47 );
System.out.println(n1 == n2);
System.out.println(n1 != n2);
}
}

打印

1
false,true

感觉以上的例子并没有说明什么看看下面的这个String的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

public class TestRef {
public static void main(String[] args) {
String s = new String( "a" );
if (s == "a" )
System.out.println( " true1 " );
if (s.equals( "a" ))
System.out.println( " true2 " );
String ss = "a" ;
if (ss == "a" )
System.out.println( " true3 " );
if (ss.equals( "a" ))
System.out.println( " true4 " );
}
}

这个打印

1
true2,true3,true4

因为new String()时在堆中生成了空间给"a",对于第一次的s=="a"时,栈分配空间给"a",并把"a"当成一个匿名的对象。赋值ss="a",意味着在栈中分配了空间给"a",并把"a"这个匿名的对象引用赋给ss。所以s"a"的引用不等。而"a"再次出现在代码中时,编译器查找到先前的"a"对象,而不是再分配内存给"a"。所以ss"a"的引用是相等的。但不管引用是否相等,其值都是"a",这便看出了equals()的威力。

下载地址:

http://ss.hnu.cn/newweb/students/yuankan/download/ 院刊2.rar

将地址贴到迅雷。。。。

或者访问 http://ss.hnu.cn/newweb/students/yuankan/index.htm

大一们参与进来了,感觉但是人多但力不足。。。虽然经历了培训,大一们的动手能力还是不行。

现在看来,大一的家伙们成长了很多。。

下载地址:

http://ss.hnu.cn/newweb/students/yuankan/download/ 军训特刊终.rar

将此文件名粘贴到迅雷即可。。。。

真怀念创办院刊的时候。。。

不知道为什么我每次选择都是允许匿名评论,隔一段时间就变成不允许匿名评论了。。。。

不知道是不是bug??

0%