Java Socket 多线程实例

概述

Java 网络编程的客户端和服务端编写都非常简单。客户端使用 Socket 对象与服务端交互;服务端创建 ServerSocket 对象,然后使用accept()方法进行监听,并返回一个Socket的对象。accept 方法是阻塞调用,并将一直阻塞,直到接收到下一个客户端请求为止。非多线程情况下,服务器同时只能服务一个客户端。这通常是不能满足现实需求的。

对于现实场景是通过在服务端创建多个线程来服务多个客户端,如下图:

服务端

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.concurrent.ExecutorService

;
import java.util.concurrent.Executors;

public class EchoMultiServer {
private static ServerSocket server = null;
private static ExecutorService threadPool;

public static void main(String[] args) {
threadPool = Executors.newCachedThreadPool();
threadPool.submit(new Monitor

());

try {
server = new ServerSocket(10000);

System.out.println("Server listening on port 10000 ....");
System.out.println("Hit Enter to stop the server");

while (true) {
Socket socket = server.accept();
System.out.println("Thread created");
threadPool.submit(new EchoThread

(socket));
}
} catch (SocketException e) {
System.out.println("Server is down");
} catch (IOException e) {
e.printStackTrace();
}
}

private static void shutdownServer() {
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}

threadPool.shutdown();
System.exit(0);
}

private static class Monitor implements Runnable {

@Override
public void run() {
try {
while (System.in.read() != '\n') {}
} catch (IOException e) {
}

shutdownServer();
}
}
}

class EchoThread implements Runnable {
private Socket socket = null;
private byte[] buffer = new byte[512];

public EchoThread(Socket socket) {
this.socket = socket;
}

@Override
public void run() {
try {
InputStream is = socket.getInputStream();
is.read(buffer);
OutputStream os = socket.getOutputStream();
os.write(buffer);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

客户端

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
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress

;
import java.net.Socket;
import java.util.Scanner;

public class EchoMultiClient {
private static int counter;

public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
counter++;
new Thread(new Client(counter)).start();
}
}

private static class Client implements Runnable {
private int counter;

public Client(int counter) {
this.counter = counter;
}

@Override
public void run() {
try {
Socket socket = new Socket();
socket.connect(new InetSocketAddress("localhost", 10000), 1000);

try {
OutputStream os = socket.getOutputStream();
String str = "Hello from Client " + counter;
os.write(str.getBytes());
InputStream is = socket.getInputStream();
Scanner scanner = new Scanner(is);
while (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}

Thread.sleep(10);
scanner.close();
} finally {
socket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}