实现服务器

使用ServerSocket类实现服务器

下面的代码使用了ServerSocket类建立一个套接字

1
2
3
4
5
6
7
8
9
10
11
12
ServerSocket s = new ServerSocket(8189);
//服务器占用的端口号为8189
Socket incoming = s.accept();
//等待客户端的连接,每有一个客户端连接到该服务器,都会获得一个Socket对象
InputStream inStream = incoming.getInputStream();
OutputStream outStream = incoming.getOutputStream();
//获得相应的输入输出流,它的输出为客户端的输入,它的输入为客户端的输出
Scanner in=new Scanner(inStream);
PrintWriter out = new PrintWriter(out);
//实例化相应的读入器和写入器,方便操作
out.println("hello! Enter BYB to exit");//给客户端的问候信息
incoming.close()//记得关闭套接字

每一个服务器程序,都不间断的执行下面这个循环操作

  1. 通过输入数据流从客户端接收一个命令
  2. 解码这个命令
  3. 收集客户端所请求的信息
  4. 通过输出数据流发送信息给客户端

示例代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import java.io.*;
import java.net.*;
import java.util.*;
public class EchoServer
{
public static void main(String[] args)
{
try
{
// establish server socket
ServerSocket s = new ServerSocket(8189);

// wait for client connection
Socket incoming = s.accept();
try
{
InputStream inStream = incoming.getInputStream();
OutputStream outStream = incoming.getOutputStream();

Scanner in = new Scanner(inStream);
PrintWriter out = new PrintWriter(outStream, true /* autoFlush */);

out.println("Hello! Enter BYE to exit.");

// echo client input
boolean done = false;
while (!done && in.hasNextLine())
{
String line = in.nextLine();
out.println("Echo: " + line);
if (line.trim().equals("BYE")) done = true;
}
}
finally
{
incoming.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}

为多个客户端服务

为了实现同时为多个客户端服务,服务器应该有类似以下代码的循环操作

1
2
3
4
5
6
while(true){
Socket incoming = s.accept();
Runnable r= new ThreadedEchoHander(incoming);
Thread t = new Thread(r);
t.start();
}

ThreadedEchoHander类实现了Runnable接口,而且在它的run方法中包含了与客户端循环通信的代码。

1
2
3
4
5
6
7
8
9
10
11
12
class ThreadedEchoHandler implements Runnable{
public void run(){
try{
InputStream inStream=incoming.getInputStream();
OutputStream outStream = incoming.getOutputStream();
process input and send response
incoming.close();
}catch(IOException e){
handle exception
}
}
}

每一个连接都会启动一个新的线程,因而多个客户端就可以同时连接到服务器了。

示例程序如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import java.io.*;
import java.net.*;
import java.util.*;
public class ThreadedEchoServer
{
public static void main(String[] args )
{
try
{
int i = 1;
ServerSocket s = new ServerSocket(8189);

while (true)
{
Socket incoming = s.accept();
System.out.println("Spawning " + i);
Runnable r = new ThreadedEchoHandler(incoming);
Thread t = new Thread(r);
t.start();
i++;
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
class ThreadedEchoHandler implements Runnable
{
public ThreadedEchoHandler(Socket i)
{
incoming = i;
}

public void run()
{
try
{
try
{
InputStream inStream = incoming.getInputStream();
OutputStream outStream = incoming.getOutputStream();

Scanner in = new Scanner(inStream);
PrintWriter out = new PrintWriter(outStream, true /* autoFlush */);

out.println( "Hello! Enter BYE to exit." );

// echo client input
boolean done = false;
while (!done && in.hasNextLine())
{
String line = in.nextLine();
out.println("Echo: " + line);
if (line.trim().equals("BYE"))
done = true;
}
}
finally
{
incoming.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}

private Socket incoming;
}

半关闭

半关闭:套接字连接的一端可以终止其输出,同时仍旧可以接受来自另一端的数据。

可以通过关闭一个套接字的输出流来表示发送给服务器的请求数据已经结束,但是必须保持输入流处于打开状态。

1
2
3
4
5
6
7
8
9
10
11
12
Socket socket=new Socket(host,port);
Scanner in=new Scanner(socket.getInputStream());
PrintWriter writer=new PrintWriter(socket.getOutputStream());
writer.print(...);
writer.flush();
socket.shutdownOutput();
//已经进入半关闭
//现在还可以读数据
while(in.hasNextLine()!=null){
String line=in.nextLine();......
}
socket.close();
Donate comment here