当前位置:   article > 正文

Java基础——TCP通信_java tcp

java tcp

(1)TCP协议特点:

  • TCP是一种面向连接,安全,可靠的传输数据的协议
  • 传输前,采用“三次握手”方式,点对点通信,是可靠的
  • 在连接中可进行大数据量的传输

(2) TCP通信模式:(在java中只需使用java.net.Socket类实现通信,底层即是使用了TCP协议)

2.1:一发一收

客户端 (一发一收)

  1. import java.io.OutputStream;
  2. import java.io.PrintStream;
  3. import java.net.Socket;
  4. /**
  5. 目标:完成Socket网络编程入门案例的客户端开发,实现1发1收。
  6. */
  7. public class ClientDemo1 {
  8. public static void main(String[] args) {
  9. try {
  10. System.out.println("====客户端启动===");
  11. // 1、创建Socket通信管道请求有服务端的连接
  12. // public Socket(String host, int port)
  13. // 参数一:服务端的IP地址
  14. // 参数二:服务端的端口
  15. Socket socket = new Socket("127.0.0.1", 7777);
  16. // 2、从socket通信管道中得到一个字节输出流 负责发送数据
  17. OutputStream os = socket.getOutputStream();
  18. // 3、把低级的字节流包装成打印流
  19. PrintStream ps = new PrintStream(os);
  20. // 4、发送消息
  21. ps.println("我是TCP的客户端,我已经与你对接,并发出邀请:约吗?");
  22. ps.flush();
  23. // 关闭资源。
  24. // socket.close();
  25. } catch (Exception e) {
  26. e.printStackTrace();
  27. }
  28. }
  29. }

服务端(一发一收)

  1. import java.io.BufferedReader;
  2. import java.io.InputStream;
  3. import java.io.InputStreamReader;
  4. import java.net.ServerSocket;
  5. import java.net.Socket;
  6. /**
  7. 目标:开发Socket网络编程入门代码的服务端,实现接收消息
  8. */
  9. public class ServerDemo2 {
  10. public static void main(String[] args) {
  11. try {
  12. System.out.println("===服务端启动成功===");
  13. // 1、注册端口
  14. ServerSocket serverSocket = new ServerSocket(7777);
  15. // 2、必须调用accept方法:等待接收客户端的Socket连接请求,建立Socket通信管道
  16. Socket socket = serverSocket.accept();
  17. // 3、从socket通信管道中得到一个字节输入流
  18. InputStream is = socket.getInputStream();
  19. // 4、把字节输入流包装成缓冲字符输入流进行消息的接收
  20. BufferedReader br = new BufferedReader(new InputStreamReader(is));
  21. // 5、按照行读取消息
  22. String msg;
  23. if ((msg = br.readLine()) != null){
  24. System.out.println(socket.getRemoteSocketAddress() + "说了:: " + msg);
  25. }
  26. } catch (Exception e) {
  27. e.printStackTrace();
  28. }
  29. }
  30. }

2.2:多发多收(单线程)

注意:目前的服务端不可以同时接收多个客户端的信息,因为目前服务端现在只有一个线程,只能与一个客户端进行通信。

客户端(多发多收:单线程,使用循环反复地发送消息)

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

服务端(多发多收:单线程,使用循环反复的接收消息)

  1. import java.io.BufferedReader;
  2. import java.io.InputStream;
  3. import java.io.InputStreamReader;
  4. import java.net.ServerSocket;
  5. import java.net.Socket;
  6. /**
  7. 目标:开发Socket网络编程入门代码的服务端,实现接收消息
  8. */
  9. public class ServerDemo2 {
  10. public static void main(String[] args) {
  11. try {
  12. System.out.println("===服务端启动成功===");
  13. // 1、注册端口
  14. ServerSocket serverSocket = new ServerSocket(7777);
  15. while (true) {
  16. // 2、必须调用accept方法:等待接收客户端的Socket连接请求,建立Socket通信管道
  17. Socket socket = serverSocket.accept();
  18. // 3、从socket通信管道中得到一个字节输入流
  19. InputStream is = socket.getInputStream();
  20. // 4、把字节输入流包装成缓冲字符输入流进行消息的接收
  21. BufferedReader br = new BufferedReader(new InputStreamReader(is));
  22. // 5、按照行读取消息
  23. String msg;
  24. while ((msg = br.readLine()) != null){
  25. System.out.println(socket.getRemoteSocketAddress() + "说了:: " + msg);
  26. }
  27. }
  28. } catch (Exception e) {
  29. e.printStackTrace();
  30. }
  31. }
  32. }

2.3:多发多收(多线程)

客户端(多发多收:多线程) 

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

服务端(多发多收:多线程) 

  1. import java.net.ServerSocket;
  2. import java.net.Socket;
  3. /**
  4. 目标:实现服务端可以同时处理多个客户端的消息。
  5. */
  6. public class ServerDemo3 {
  7. public static void main(String[] args) {
  8. try {
  9. System.out.println("===服务端启动成功===");
  10. // 1、注册端口
  11. ServerSocket serverSocket = new ServerSocket(7777);
  12. // a.定义一个死循环由主线程负责不断的接收客户端的Socket管道连接。
  13. while (true) {
  14. // 2、每接收到一个客户端的Socket管道,交给一个独立的子线程负责读取消息
  15. Socket socket = serverSocket.accept();
  16. System.out.println(socket.getRemoteSocketAddress()+ "它来了,上线了!");
  17. // 3、开始创建独立线程处理socket
  18. new ServerReaderThread(socket).start();
  19. }
  20. } catch (Exception e) {
  21. e.printStackTrace();
  22. }
  23. }
  24. }

(定义一个线程类)

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

2.4:线程池

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

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

客户端(线程池:处理多个客户端消息,解决多线程N-N的关系,导致资源浪费的问题)

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

 2.8服务端(线程池:处理多个客户端消息,解决多线程N-N的关系,导致资源浪费的问题)

  1. import java.net.ServerSocket;
  2. import java.net.Socket;
  3. import java.util.concurrent.*;
  4. /**
  5. 目标:实现服务端可以同时处理多个客户端的消息。
  6. */
  7. public class ServerDemo4 {
  8. // 使用静态变量记住一个线程池对象
  9. private static ExecutorService pool = new ThreadPoolExecutor(300,
  10. 1500, 6, TimeUnit.SECONDS,
  11. new ArrayBlockingQueue<>(2)
  12. , Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
  13. public static void main(String[] args) {
  14. try {
  15. System.out.println("===服务端启动成功===");
  16. // 1、注册端口
  17. ServerSocket serverSocket = new ServerSocket(6666);
  18. // a.定义一个死循环由主线程负责不断的接收客户端的Socket管道连接。
  19. while (true) {
  20. // 2、每接收到一个客户端的Socket管道,
  21. Socket socket = serverSocket.accept();
  22. System.out.println(socket.getRemoteSocketAddress()+ "它来了,上线了!");
  23. // 任务对象负责读取消息。
  24. Runnable target = new ServerReaderRunnable(socket);
  25. pool.execute(target);
  26. }
  27. } catch (Exception e) {
  28. e.printStackTrace();
  29. }
  30. }
  31. }

(定义一个任务类) 

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

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号