JAVA - Socket
从开学到现在 也学了三个月时间的java了,一直在 在 语法和基本使用上周旋,井底之娃一枚。 这两天 有学长指点,花了两天的时间 学习了java多线程和socket的简单使用,利用周末时间 自己写了个 Socket 多客户端的 Demo,有很多不成熟或者不好的 地方,请指正。
TCP 的 Java 支持
协议相当于相互通信的程序间达成的一种约定,它规定了分组报文的结构、交换方式、包含的意义以及怎样对报文所包含的信息进行解析,TCP/IP 协议族有 IP 协议、TCP 协议和 UDP 协议。现在 TCP/IP 协议族中的主要 socket 类型为流套接字(使用 TCP 协议)和数据报套接字(使用 UDP 协议)。
Socket套接字 是面向连接的通信,基于TCP/IP协议提供了稳定的支持(Ps: TCP/IP 传输效率低于 UDP),TCP/IP 提供了Socket和Serversocket两个类, 使用 Serversocket 实例来监听端口是否 有客户端请求,并通过 accept()方法 来返回一个Socket 实例,客户端的socket和服务端的socket 就这样建立了连接,每个socket 有自己的io流 ,那么服务端的输入流对应客户端的输出流,客户端的输出流对应服务端的输入流,在这里输入流 我们采用(BufferedReader)包装流,输入采用(PrintStream)包装流,通过包装流 包装 输入输初流,可以方便程序数据的使用。
典型的 TCP 服务端执行如下两步操作:
创建一个 ServerSocket 实例并指定本地端口,用来监听客户端在该端口发送的 TCP 连接请求;
- 重复执行:
- 调用 ServerSocket 的 accept()方法以获取客户端连接,并通过其返回值创建一个 Socket 实例;
- 为返回的 Socket 实例开启新的线程,并使用返回的 Socket 实例的 I/O 流与客户端通信; 通信完成后,使用 Socket 类的 close()方法关闭该客户端的
套接字连接。
好了话不多说,下面贴程序。
***服务端代码***
1 package socket多客户端;
2
3
4 import java.io.IOException;
5 import java.net.*;
6 import java.util.ArrayList;
7 public class Server {
8
9 private static ArrayList<Thread_Client> list = new ArrayList<>();
10
11 private static final int PORT = 6789;
12 private static ServerSocket serverSocket;
13 private static Socket socket;
14
15 static void send(String string){
16
17 // 使用 for 循环 , 遍历Arraylist 广播某客户端传来的消息
18 for(Thread_Client thread_Client : list){
19 // 调用 子线程的 send 方法
20 thread_Client.send(string);
21 }
22
23 }
24
25
26 public static void main(String[] args) {
27
28
29
30 System.out.println("服务端开始运行...");
31
32 try {
33
34 serverSocket = new ServerSocket(PORT);
35
36 while(true){
37 socket = serverSocket.accept();
38 Thread_Client thread_Client = new Thread_Client(socket);
39 thread_Client.start();
40 System.out.println("已连接!");
41 list.add(thread_Client);
42
43 }
44
45
46 } catch (Exception e) {
47 // TODO: handle exception
48 System.out.println("服务端异常1");
49 }finally {
50
51 try {
52 socket.close();
53 serverSocket.close();
54
55 } catch (IOException e2) {
56 // TODO: handle exception
57 System.out.println("服务端异常2");
58 }
59
60 }
61
62 }
63
64 }
*** 然后是 处理连接后socket 的子线程***
1 package socket多客户端;
2
3 import java.io.BufferedReader;
4 import java.io.IOException;
5 import java.io.InputStreamReader;
6 import java.io.PrintStream;
7 import java.lang.*;
8 import java.net.Socket;
9
10 public class Thread_Client extends Thread{
11
12 private BufferedReader bufferedReader = null;
13 private PrintStream printStream = null;
14
15 Socket socket;
16
17 public Thread_Client(Socket socket) {
18 //
19 this.socket = socket;
20 }
21
22 @Override
23 public void run() {
24 // TODO Auto-generated method stub
25 super.run();
26
27 try {
28 Get_Set(socket);
29
30 } catch (Exception e) {
31 // TODO: handle exception
32 System.out.println("异常1");
33 }
34
35 }
36
37 public void send(String string){
38 if(string != null){
39 printStream.println(string);
40 printStream.flush();
41 }
42 }
43
44 public void Get_Set(Socket socket){
45
46 try {
47 bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
48 printStream = new PrintStream(socket.getOutputStream());
49
50 Boolean flag = true;
51 while(flag){
52 String string = bufferedReader.readLine();
53 if("".equals(string) || string == null){
54 flag = false;
55 }else{
56 if("end".equals(string)){
57 flag = false;
58 }else{
59 System.out.println("read : " + string);
60 //调用 主线程 广播
61 Server.send(string);
62 }
63 }
64 }
65
66 } catch (IOException e) {
67 // TODO: handle exception
68 System.out.println("异常2");
69 }
70 }
71
72 }
*** 最后是 客户端代码 ***
1 package socket多客户端;
2
3 import java.io.*;
4 import java.net.*;
5 import java.util.Scanner;
6
7 public class Client {
8
9
10 private static Socket socket;
11 private static BufferedReader bufferedReader;
12 private static PrintStream printStream;
13
14 // 将 读服务端数据封装在 Client—read 方法里
15 public static void Client_read(Socket socket){
16 // 匿名内部类 开 一个子线程
17 new Thread(new Runnable() {
18 private BufferedReader bufferedReader_ec;
19
20 @Override
21 public void run() {
22 // TODO Auto-generated method stub
23
24 try {
25 bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
26 String str = bufferedReader.readLine();
27 if("".equals(str) || str == null || "end".equals(str)){
28
29 }else{
30 System.out.println(str);
31 }
32
33 } catch (Exception e) {
34 // TODO: handle exception
35 }
36 }
37 }).start();
38 }
39
40 // Get_Set 方法 处理 客户端与服务端 数据的读写
41 static void Get_Set(Socket socket){
42
43 try {
44 bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
45 printStream = new PrintStream(socket.getOutputStream());
46 Scanner keyboard = new Scanner(System.in);
47
48 Boolean flag = true;
49 while(flag){
50
51 // 在这里调用 之前封装的 Client_read 方法
52 Client_read(socket);
53
54 // 从 键盘 输入数据
55 String shuru = keyboard.nextLine();
56 if("".equals(shuru) || shuru == null){
57 flag = false; // 通过 嵌套if else 筛掉无用值
58 }else{
59 if("end".equals(shuru)){
60 flag = false;
61 }else{
62 printStream.println(shuru); // 发送至服务端
63 printStream.flush();
64 }
65 }
66
67
68 }
69
70
71 } catch (Exception e) {
72 // TODO: handle exception
73 }
74
75
76 }
77
78 public static void main(String[] args) {
79
80 try {
81
82 socket = new Socket("localhost",6789);
83 System.out.println("客户端已连接至服务端!");
84 Get_Set(socket);
85
86 } catch (Exception e) {
87 // TODO: handle exception
88 System.out.println("客户端异常1");
89 }finally {
90 try {
91 printStream.close();
92 bufferedReader.close();
93 socket.close();
94
95 } catch (Exception e2) {
96 // TODO: handle exception
97 System.out.println("客户端异常2");
98 }
99 }
100
101
102 }
103
104
105 }
好了 ,下面我们来运行 看看结结果。
第一个控制台是 服务端
第二个控制台是 客户端1
第三个控制台是 客户端2
这样我们就实现了 一个简单的基于TCP/IP协议的socket多客户端通信。
笔者 还是个 编程菜鸟,有什么不好的地方,希望各位大牛可以指正。
知道自己想要什么的人,每一步都在路上。