当前位置:   article > 正文

TCP协议_socket.getinput

socket.getinput

1、什么是TCP协议呢?

1.TCP是一种面向连接,安全、可靠的传输数据的协议。

2.传输前,采用“三次握手”方式,点对点通信,是可靠的 。

3.在连接中可进行大数据量的传输。

注意: 如果在java中只要是使用java.net.Socket类实现通信,底层即是使用了TCP协议。

Socket

构造器

说明

public Socket(String host , int port)​

创建发送端的Socket对象与服务端连接,参数为服务端程序的ip和端口。

Socket类成员方法

方法

说明

OutputStream getOutputStream()

获得字节输出流对象(发)

InputStream getInputStream()

获得字节输入流对象(收)

需求:服务端实现

实现步骤:

 1.创建ServerSocket对象,注册服务端端口。

2.调用ServerSocket对象的accept()方法,等待客户端的连接,并得到Socket管道对象。

3.通过Socket对象调用getInputStream()方法得到字节输入流、完成数据的接收。

4.释放资源:关闭socket管道

ServerSocket代码实现服务端:

服务端代码:

  1. public static void main(String[] args) {
  2. try {
  3. System.out.println("===========服务端启动了==========");
  4. //1、注册端口
  5. ServerSocket serverSocket = new ServerSocket(7777);
  6. //2、必须调用accept方法,等待接受用户的Socket链接请求,建立Socket通信管道
  7. Socket socket = serverSocket.accept();
  8. //3、从socket通信管道中得到一个字节输入流
  9. InputStream is = socket.getInputStream();
  10. //4、把字节输入流包装缓冲字符输入流进行消息接收
  11. BufferedReader br = new BufferedReader(new InputStreamReader(is));
  12. //5、按照行读取消息
  13. String msg;
  14. if ((msg = br.readLine()) != null){
  15. System.out.println(socket.getRemoteSocketAddress()+"说了:"+msg);
  16. }
  17. } catch (Exception e) {
  18. e.printStackTrace();
  19. }
  20. }

需求:客户端实现

实现步骤:

1.创建客户端的Socket对象,请求与服务端的连接。

2.使用socket对象调用getOutputStream()方法得到字节输出流。

3.使用字节输出流完成数据的发送。

4.释放资源:关闭socket管道。

客户端代码:

  1. public static void main(String[] args) {
  2. try {
  3. System.out.println("==========客户端启动了============");
  4. //1、创建Socket通信管道请求与服务端链接
  5. //public Socket (String host , int port)
  6. //参数一:服务端的IP地址
  7. //参数二:服务端的端口
  8. Socket socket = new Socket("127.0.0.1",7777);
  9. //2、从socket通信管道中得到一个字节输出流 负责发送数据
  10. OutputStream os = socket.getOutputStream();
  11. //3、把低级的字节流打包成打印流
  12. PrintStream ps = new PrintStream(os);
  13. //4、发送消息
  14. ps.println("我是TCP的客户端,我已经与你对接,并发出邀请:约吗?");
  15. ps.flush();
  16. //关闭资源(不建议关闭)
  17. socket.close();
  18. } catch (Exception e) {
  19. e.printStackTrace();
  20. }
  21. }

实现结果:

 注意:一定要服务端先启动,客户端才可以启动,否则就会报错。

 ServerSocket(服务端)

构造器

说明

public ServerSocket(int port)

注册服务端端口

 ServerSocket类成员方法

方法

说明

public Socket accept()

等待接收客户端的Socket通信连接

连接成功返回Socket对象与客户端建立端到端通信

 注意:如果客户端和服务端一方出了问题,另一方也会失效或者出错。

需求:使用TCP通信实现:多发多收消息、

实现步骤:

1.可以使用死循环控制服务端收完消息继续等待接收下一个消息。

2.客户端也可以使用死循环等待用户不断输入消息。

3.客户端一旦输入了exit,则关闭客户端程序,并释放资源。

服务端代码:

  1. public static void main(String[] args) {
  2. try {
  3. System.out.println("===========服务端启动了==========");
  4. //1、注册端口
  5. ServerSocket serverSocket = new ServerSocket(7777);
  6. //2、必须调用accept方法,等待接受用户的Socket链接请求,建立Socket通信管道
  7. Socket socket = serverSocket.accept();
  8. //3、从socket通信管道中得到一个字节输入流
  9. InputStream is = socket.getInputStream();
  10. //4、把字节输入流包装缓冲字符输入流进行消息接收
  11. BufferedReader br = new BufferedReader(new InputStreamReader(is));
  12. //5、按照行读取消息
  13. String msg;
  14. while ((msg = br.readLine()) != null){
  15. System.out.println(socket.getRemoteSocketAddress()+"说了:"+msg);
  16. }
  17. } catch (Exception e) {
  18. e.printStackTrace();
  19. }
  20. }

客户端代码:

  1. public static void main(String[] args) {
  2. try {
  3. System.out.println("==========客户端启动了============");
  4. //1、创建Socket通信管道请求与服务端链接
  5. //public Socket (String host , int port)
  6. //参数一:服务端的IP地址
  7. //参数二:服务端的端口
  8. Socket socket = new Socket("127.0.0.1",7777);
  9. //2、从socket通信管道中得到一个字节输出流 负责发送数据
  10. OutputStream os = socket.getOutputStream();
  11. //3、把低级的字节流打包成打印流
  12. PrintStream ps = new PrintStream(os);
  13. Scanner sc = new Scanner(System.in);
  14. while (true) {
  15. System.out.println("请说:");
  16. String msg = sc.nextLine();
  17. //4、发送消息
  18. ps.println(msg);
  19. ps.flush();
  20. }
  21. //关闭资源(不建议关闭)
  22. // socket.close();
  23. } catch (Exception e) {
  24. e.printStackTrace();
  25. }
  26. }

实现结果:

这次多发多收是如何实现的呢?

通过客户端使用循环反复地发送消息,服务端使用循环反复地接收消息。从而实现多发多收。

注意:目前服务端是单线程的,每次只能处理一个客户端的消息。


 

使用多线程——同时接受多个客户端消息(优化多发多收)

客户端代码:

  1. package com.wfl.d7_socket3;
  2. import java.io.OutputStream;
  3. import java.io.PrintStream;
  4. import java.net.Socket;
  5. import java.util.Scanner;
  6. /**
  7. 目标: 多发多收
  8. */
  9. public class ClientDemo1 {
  10. public static void main(String[] args) {
  11. try {
  12. System.out.println("==========客户端启动了============");
  13. //1、创建Socket通信管道请求与服务端链接
  14. //public Socket (String host , int port)
  15. //参数一:服务端的IP地址
  16. //参数二:服务端的端口
  17. Socket socket = new Socket("127.0.0.1",7777);
  18. //2、从socket通信管道中得到一个字节输出流 负责发送数据
  19. OutputStream os = socket.getOutputStream();
  20. //3、把低级的字节流打包成打印流
  21. PrintStream ps = new PrintStream(os);
  22. Scanner sc = new Scanner(System.in);
  23. while (true) {
  24. System.out.println("请说:");
  25. String msg = sc.nextLine();
  26. //4、发送消息
  27. ps.println(msg);
  28. ps.flush();
  29. }
  30. } catch (Exception e) {
  31. e.printStackTrace();
  32. }
  33. }
  34. }

服务端启动代码:

  1. package com.wfl.d7_socket3;
  2. import java.io.BufferedReader;
  3. import java.io.InputStream;
  4. import java.io.InputStreamReader;
  5. import java.net.ServerSocket;
  6. import java.net.Socket;
  7. /**
  8. 目标: 实现服务端可以同时处理多个客户端消息
  9. */
  10. public class ServerDemo2 {
  11. public static void main(String[] args) {
  12. try {
  13. System.out.println("===========服务端启动了==========");
  14. //1、注册端口
  15. ServerSocket serverSocket = new ServerSocket(7777);
  16. while (true) {
  17. //2、必须调用accept方法,等待接受用户的Socket链接请求,建立Socket通信管道
  18. Socket socket = serverSocket.accept();
  19. System.out.println(socket.getRemoteSocketAddress()+"上线了~~");
  20. //3、开始创建独立的线程处理socket
  21. new ServerReaderThread(socket).start();
  22. }
  23. } catch (Exception e) {
  24. e.printStackTrace();
  25. }
  26. }
  27. }

服务端线程代码:

  1. package com.wfl.d7_socket3;
  2. import java.io.BufferedReader;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.io.InputStreamReader;
  6. import java.net.ServerSocket;
  7. import java.net.Socket;
  8. public class ServerReaderThread extends Thread{
  9. private Socket socket;
  10. public ServerReaderThread (Socket socket){
  11. this.socket = socket;
  12. }
  13. @Override
  14. public void run() {
  15. try {
  16. //3、从socket通信管道中得到一个字节输入流
  17. InputStream is = socket.getInputStream();
  18. //4、把字节输入流包装缓冲字符输入流进行消息接收
  19. BufferedReader br = new BufferedReader(new InputStreamReader(is));
  20. //5、按照行读取消息
  21. String msg;
  22. while ((msg = br.readLine()) != null){
  23. System.out.println(socket.getRemoteSocketAddress()+"说了:"+msg);
  24. }
  25. } catch (Exception e) {
  26. System.out.println(socket.getRemoteSocketAddress()+"下线了~~");
  27. }
  28. }
  29. }

重点:

1.主线程定义了循环负责接收客户端Socket管道连接

2.每接收到一个Socket通信管道后分配一个独立的线程负责处理它。

 

使用线程池优化(引入线程池)

客户端代码:

  1. package com.wfl.d8_socket4;
  2. import java.io.OutputStream;
  3. import java.io.PrintStream;
  4. import java.net.Socket;
  5. import java.util.Scanner;
  6. /**
  7. 拓展: 使用线程池优化:实现通信。
  8. */
  9. public class ClientDemo1 {
  10. public static void main(String[] args) {
  11. try {
  12. System.out.println("==========客户端启动了============");
  13. //1、创建Socket通信管道请求与服务端链接
  14. //public Socket (String host , int port)
  15. //参数一:服务端的IP地址
  16. //参数二:服务端的端口
  17. Socket socket = new Socket("127.0.0.1",7777);
  18. //2、从socket通信管道中得到一个字节输出流 负责发送数据
  19. OutputStream os = socket.getOutputStream();
  20. //3、把低级的字节流打包成打印流
  21. PrintStream ps = new PrintStream(os);
  22. Scanner sc = new Scanner(System.in);
  23. while (true) {
  24. System.out.println("请说:");
  25. String msg = sc.nextLine();
  26. //4、发送消息
  27. ps.println(msg);
  28. ps.flush();
  29. }
  30. //关闭资源(不建议关闭)
  31. // socket.close();
  32. } catch (Exception e) {
  33. e.printStackTrace();
  34. }
  35. }
  36. }

服务端代码:采用线程池。

  1. package com.wfl.d8_socket4;
  2. import com.wfl.d7_socket3.ServerReaderThread;
  3. import java.net.ServerSocket;
  4. import java.net.Socket;
  5. import java.util.concurrent.*;
  6. /**
  7. 目标: 实现服务端可以同时处理多个客户端消息
  8. */
  9. public class ServerDemo2 {
  10. //使用静态变量记住一个线程池对象
  11. private static ExecutorService pool = new ThreadPoolExecutor(3,
  12. 5,6, TimeUnit.SECONDS,new ArrayBlockingQueue<>(2),
  13. Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
  14. public static void main(String[] args) {
  15. try {
  16. System.out.println("===========服务端启动了==========");
  17. //1、注册端口
  18. ServerSocket serverSocket = new ServerSocket(7777);
  19. while (true) {
  20. //2、必须调用accept方法,等待接受用户的Socket链接请求,建立Socket通信管道
  21. Socket socket = serverSocket.accept();
  22. System.out.println(socket.getRemoteSocketAddress()+"上线了~~");
  23. //任务对象负责读取消息
  24. Runnable srr = new ServerReaderRunnable(socket);
  25. pool.execute(srr);
  26. }
  27. } catch (Exception e) {
  28. e.printStackTrace();
  29. }
  30. }
  31. }
  1. package com.wfl.d8_socket4;
  2. import java.io.BufferedReader;
  3. import java.io.InputStream;
  4. import java.io.InputStreamReader;
  5. import java.net.Socket;
  6. public class ServerReaderRunnable implements Runnable {
  7. private Socket socket;
  8. public ServerReaderRunnable(Socket socket){
  9. this.socket = socket;
  10. }
  11. @Override
  12. public void run() {
  13. try {
  14. //3、从socket通信管道中得到一个字节输入流
  15. InputStream is = socket.getInputStream();
  16. //4、把字节输入流包装缓冲字符输入流进行消息接收
  17. BufferedReader br = new BufferedReader(new InputStreamReader(is));
  18. //5、按照行读取消息
  19. String msg;
  20. while ((msg = br.readLine()) != null){
  21. System.out.println(socket.getRemoteSocketAddress()+"说了:"+msg);
  22. }
  23. } catch (Exception e) {
  24. System.out.println(socket.getRemoteSocketAddress()+"下线了~~");
  25. }
  26. }
  27. }

使用线程池的优势:

服务端可以复用线程处理多个客户端,可以避免系统瘫痪。

适合客户端通信时长较短的场景。

即时通信是啥?

即时通信,是指一个客户端的消息发出去,其他客户端可以接收到。

要咋设计?

1.即时通信需要进行端口转发的设计思想。

2.服务端需要把在线的Socket管道存储起来

3.一旦收到一个消息要推送给其他管道

实例:微信群发,就是即时通信的思想!

TCP通信如何实现BS请求网页信息回来呢?

1.客户端使用浏览器发起请求(不需要开发客户端)

2.服务端必须按照浏览器的协议规则响应数据。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/356670
推荐阅读
相关标签
  

闽ICP备14008679号