★Sockets 使用TCP协议实现网络通信的Socket相关类(重点)
TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议
服务器端的ServerSocket类 客户端的Socket类
①.服务器端通信流程 ②. 客户端通信流程
1. 创建ServerSocket对象,绑定该程序使用的端口 1. 创建Socket对象,指明服务器的IP地址和通信程序的端口号
2. 建立accept()方法监听客户端请求 2. 建立链接后,通过输出流向服务器发送请求连接。
3. 建立连接后,通过输入流读取客户端放送的请求信息 3. 通过输入流获得服务器的响应信息。
4. 通过输出流向客户端发送响应信息 4. 重复2,3
5. 重复3,4 5. 关闭相关资源
6. 关闭相关资源
注意: 我的示例代码客户端和服务器都是本机
一. TCP基础的C/S通信
示例代码省略了客户端重复发送请求的步骤
示例代码:
服务器端
1 public static void main(String[] args) { 2 try { 3 //1.创建一个服务器端Socket,即ServerSicket,指定绑定端口,并监听此端口 4 ServerSocket serverSocket = new ServerSocket(888); 5 System.out.println("***服务器即将启动,等待客户端的连接***"); 6 //2.通过accept()方法监听客户端请求,若接到请求服务器会返回一个socket对象进行通信 7 Socket socket = serverSocket.accept(); 8 //3.建立连接后,通过输入流读取客户端发送的信息 9 InputStream is = socket.getInputStream();//获取资源的字节输入流 10 InputStreamReader isr = new InputStreamReader(is);//字节输入流转字符输入流 11 BufferedReader buffer = new BufferedReader(isr);//为字符输入流添加缓冲 12 String info = null; 13 while((info = buffer.readLine()) != null){ 14 System.out.println("客户端发送的信息:" + "\n" + info + "\n"); 15 } 16 socket.shutdownInput();//关闭输入流 17 //4.通过输出流向客户端放送相应信息 18 OutputStream os = socket.getOutputStream();//获取字节输出流 19 PrintWriter pw = new PrintWriter(os);//将输出流打包为打印流 20 pw.write("欢迎您!\n"); 21 pw.flush();//刷新 22 socket.shutdownOutput();//关闭输出流 23 //5.关闭资源 24 pw.close(); 25 os.close(); 26 buffer.close(); 27 isr.close(); 28 is.close(); 29 socket.close(); 30 serverSocket.close(); 31 } catch (IOException e) { 32 e.printStackTrace(); 33 } 34 }
客户端:
1 public static void main(String[] args) { 2 try { 3 //1.创建Socket对象,指明需要连接的服务器地址和端口号 4 Socket socket = new Socket("localhost",888); 5 //2.链接后通过输出流向服务器端放送请求信息 6 OutputStream os = socket.getOutputStream(); 7 PrintWriter pw = new PrintWriter(os); 8 pw.write("用户名:admin;密码:4399"); 9 pw.flush();//刷新 10 socket.shutdownOutput();//关闭输出流 11 //3.通过输出流获取服务器响应的信息 12 InputStream is = socket.getInputStream(); 13 InputStreamReader isr = new InputStreamReader(is); 14 BufferedReader buffer = new BufferedReader(isr); 15 String info = null; 16 while((info = buffer.readLine()) != null){ 17 System.out.println(info); 18 } 19 socket.shutdownInput();//关闭输入流 20 //4.关闭相关资源 21 buffer.close(); 22 isr.close(); 23 is.close(); 24 pw.close(); 25 os.close(); 26 socket.close(); 27 } catch (UnknownHostException e) { 28 e.printStackTrace(); 29 } catch (IOException e) { 30 e.printStackTrace(); 31 } 32 }
输出结果
1.开始。服务器端:
***服务器即将启动,等待客户端的连接***
服务器运行带accept()方法,处于阻塞状态,等待客户端发送信息响应连接
2.建立链接后。服务器端: 客户端:
***服务器即将启动,等待客户端的连接*** 欢迎您!
客户端发送的信息:
用户名:admin;密码:4399
实际就是ServerSocket的accept()方法监测到客户端的请求之后生成一个服务器的Scoket对象
实际就是两个Scoket对象在进行通信 Socket = IP地址 + 端口号
二. 进阶版,多线程TCP的C/S通信
上诉例子只实现了一台服务器和一台客户机的通信,但实际情况通常都是一台服务器对应多个客户端的情况,要解决这个方法,我们引用了线程。
示例代码:(客户端代码不变)
客户端:
1 public static void main(String[] args) { 2 try { 3 //创建一个服务器端Socket,即ServerSicket,指定绑定端口,并监听此端口 4 ServerSocket serverSocket = new ServerSocket(888); 5 System.out.println("***服务器即将启动,等待客户端的连接***"); 6 Socket socket = null; 7 //通过accept()方法循环监听客户端请求,若接到请求服务器会返回一个socket对象进行通信 8 while(true){ 9 socket = serverSocket.accept(); 10 ServerThread serverThread = new ServerThread(socket); 11 serverThread.start(); 12 System.out.println("客户端" + socket.getInetAddress().getHostAddress() + "说:"); 13 } 14 } catch (IOException e) { 15 e.printStackTrace(); 16 } 17 }
1 public class ServerThread extends Thread { 2 3 Socket socket = null; 4 5 public ServerThread(Socket socket){ 6 this.socket = socket; 7 } 8 9 public void run(){ 10 InputStream is = null; 11 InputStreamReader isr = null; 12 BufferedReader buffer = null; 13 OutputStream os = null; 14 PrintWriter pw = null; 15 try { 16 //建立连接后,通过输入流读取客户端发送的信息 17 is = socket.getInputStream(); 18 isr = new InputStreamReader(is); 19 buffer = new BufferedReader(isr); 20 String info = null; 21 while((info = buffer.readLine()) != null){ 22 System.out.println( info + "\n"); 23 } 24 socket.shutdownInput();//关闭输入流 25 //通过输出流向客户端放送相应信息 26 os = socket.getOutputStream(); 27 pw = new PrintWriter(os); 28 pw.write("欢迎您!\n"); 29 pw.flush();//刷新 30 socket.shutdownOutput();//关闭输出流 31 } catch (IOException e) { 32 e.printStackTrace(); 33 } finally{ 34 //关闭资源 35 try { 36 if(pw != null) 37 pw.close(); 38 if(os != null) 39 os.close(); 40 if(buffer != null) 41 buffer.close(); 42 if(isr != null) 43 isr.close(); 44 if(is != null) 45 is.close(); 46 if(socket != null) 47 socket.close(); 48 } catch (IOException e) { 49 // TODO Auto-generated catch block 50 e.printStackTrace(); 51 } 52 } 53 } 54 }
运行结果:
***服务器即将启动,等待客户端的连接***
客户端127.0.0.1说:
用户名:admin;密码:4399
客户端127.0.0.1说:
用户名:xiaolai;密码:1104
这里其实是有两个客户端与服务器进行了响应,因为两个客户端都是我的本机,所以IP地址会相同。
运用一个死循环执行accept()语句。
只要有客户端发送请求,服务器就会生成一个Socket对象,开启线程与一个客户端通信,
多个客户端发送请求,服务器就会不停的切换生成Socket对象,并开启线程进行通信
从而实现了一个服务器通过多线程的方法与数台客户机通信。
如果有什么错误,或者我理解错误或不当的,恳请大家纠正,谢谢!嘻嘻嘻~