引言

所谓网络编程,指的就是通过编写程序使得计算机可以相互通信,生活中很多软件都是融合了网络编程的,比如QQ 等通信app。网络编程通常是为现有App增强连接到服务端的能力,但是有些事基于TCP,有些是基于HTTP。狭义的网络编程,指的是通信聊天类型的应用,广义的是凡是接入网络的程序,都是网络编程。

一.网络基础知识

1.1 网络模型

网络通信最初的设计模型为OSI 7层通信模型,所谓网络模型就是科学家对应如何实现网络通信的一种设计和设想。一个科学领域的某些技术往往都是先建立问题模型,然后再做实现。

1.1.1 OSI模型

image.png

1.1.2 TCP/IP模型

image.png

1.2 IP地址

IP 也就是IP地址协议,它的作用就是标记网络中每台计算机的身份。网络中的每个计算机都有唯一的一个地址。

1.2.1 IP地址表示

  • IPv4

它是由一个4字节32位的整数表示,为了方便记忆,使用点分10进制表示D.D.D.D,每8位使用一个0-255表示,用 . 分隔。 平时见到的 如192.128.1.12 这种就是 IPv4地址表示。

由于 表示容量的 问题 ,IPv4 早已不够使用,它的下一个版本IPv6 拥有更大的表示范围。

  • IPv6

它是由一个16字节128位的整数表示,表示的范围更大,也就意味着IP地址越多,夸张到 沙漠中每一粒沙子都可以分配到一个IP,它使用8段16进制表示,每段0-65535。X.X.X.X.X.X.X.X 。

1.2.2 IP地址分类

image.png

1.3 端口

端口,计算机上通信程序的唯一标识,计算机中存在多网络软件,如何区分开不同的软件,就需要使用端口。不同的应用只通过固定端口收发数据。
端口的范围 0-65535

1.3.1 常见默认端口

MySQL-> 3306
Tomcat->8080
HTTP->80
SSH->22
FTP->21

1.4 TCP/UDP

1.4.1 TCP 特点

1)TCP是面向连接的运输层协议。应用程序在使用TCP协议之前,必须先建立TCP连接,在传送数据完毕后,必须释放已经建立的TCP连接。
(2)每一条TCP连接只能有两个端点,即点对点的。
(3)TCP提供可靠交付的服务。通过TCP连接传送的数据,无差错、不丢失、不重复、并且按序到达。
(4)TCP提供全双工通信。TCP允许通信双方的应用进程在任何时候都能发送数据。
(5)面向字节流。TCP中的“流”指的是流入到进程或从进程流出的字节序列。面向字节流的含义是:虽然应用程序和TCP的交互是一次一个数据块(大小不等),但是TCP把应用程序交下来的数据仅仅看成是一连串的无结构的字节流。

1.4.2 UDP 特点

(1)UDP是无连接的,即发送数据之前不需要建立连接(当然,发送数据结束时也没有连接可以释放),因此减少了开销和发送数据之前的时延。
(2)UDP使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的连接状态表(这里面有很多参数)。
(3)UDP是面向报文的。发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付IP层。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。这就是说,应用层交给UDP多长 的报文,UDP就照样发送,即一次发送一个报文。
(4)UDP没有拥塞控制,因此网络出现的拥塞不会使源主机的发送速率降低。但是不使用拥塞控制功能的UDP有可能会引起网络产生严重的拥塞问题。
(5)UDP支持一对一、一对多、多对一和多对多的交互通信。
(6)UDP的首部开销小,只有8个字节,比TCP的20个字节的首部还要短。
UDP也用在路由信息协议RIP(Routing Information Protocol)中修改路由表。在这些应用场合下,如果有一个消息丢失,在几秒之后另一个新的消息就会替换它。UDP广泛用在多媒体应用中。

1.4.3 三次握手

src=http___nimg.ws.126.net__url=http%3A%2F%2Fdingyue.ws.126.net%2F2021%2F0328%2F12865b7ej00qqo1ob000uc000hs00bag.jpg&thumbnail=650x2147483647&quality=80&type=jpg&refer=http___nimg.ws.126.jpg

1.4.5 四次挥手

src=http___nimg.ws.126.net__url=http%3A%2F%2Fdingyue.ws.126.net%2F2021%2F0328%2Fe3887080j00qqo1oc000yc000hs00bsg.jpg&thumbnail=650x2147483647&quality=80&type=jpg&refer=http___nimg.ws.126 (1).jpg

二.Socket编程

2.1 Socket 编程流程

  • 服务器端使用ServerSocket套接字 并绑定监听端口
  • 服务端 阻塞等待连接
  • 客户端使用 Socket 并指定服务端IP 和 端口

服务端:

  1. //1. 服务器端套接字
  2. ServerSocket server = new ServerSocket(8848);
  3. //2. 监听客户端连接
  4. Socket socket = server.accept();

客户端

  1. //1. 创建客户端套接字
  2. Socket socket = new Socket( "127.0.0.1" , 8848);

2.2 Socket 收发数据

从Socket中读数据

  1. InputStream is = socket.getInputStream();
  2. byte[] buff = new byte[1024];
  3. int len=0;
  4. while ( (len=is.read(buff))!=-1){
  5. //读到了客户端发的字节信息
  6. System.out.println( new String(buff,0,len) );
  7. }

从写数据到Socket中

  1. //发送数据给服务端
  2. BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
  3. bos.write("hello".getBytes());

2.3 多客户端连接

  1. while (true) {
  2. System.out.println("等待连接中.......");
  3. //接收客户端连接
  4. Socket socket = server.accept();
  5. }

2.4 多客户端通信

  1. //服务端
  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. import java.net.ServerSocket;
  5. import java.net.Socket;
  6. import java.util.ArrayList;
  7. import java.util.List;
  8. @SuppressWarnings("all")
  9. public class sever {
  10. public static List<Socket> socketList = new ArrayList<>();
  11. public static void main(String[] args) throws IOException {
  12. ServerSocket serverSocket = new ServerSocket(7777);
  13. while (true){
  14. System.out.println("等待客户端连接");
  15. Socket socket = serverSocket.accept();
  16. socketList.add(socket);
  17. //在这里读数据阻塞线程,在这里启动一个新的线程单独处理读取这个客户端的信息
  18. new Thread(new serverThread(socket)).start();
  19. }
  20. }
  21. }
  22. class serverThread implements Runnable{
  23. private Socket socket;
  24. //构建任务时初始化客户端
  25. public serverThread(Socket socket) {
  26. this.socket = socket;
  27. }
  28. @Override
  29. public void run() {
  30. try{
  31. InputStream is = socket.getInputStream();
  32. byte[] bs = new byte[1024];
  33. int len;
  34. while (( len=is.read(bs))!=-1){
  35. String msg = new String(bs,0,len);
  36. for (Socket socket1 : sever.socketList) {
  37. if (socket1==this.socket)continue;
  38. socket1.getOutputStream().write(msg.getBytes());
  39. }
  40. }
  41. }catch(IOException e){
  42. e.printStackTrace();
  43. }
  44. }
  45. }
  46. //客户端
  47. package NET3;
  48. import java.io.IOException;
  49. import java.io.InputStream;
  50. import java.io.OutputStream;
  51. import java.net.Socket;
  52. import java.util.Scanner;
  53. public class client {
  54. public static void main(String[] args) throws IOException {
  55. Socket socket = new Socket("127.0.0.1",7777);
  56. OutputStream outputStream = socket.getOutputStream();
  57. new Thread(new clientThread(socket)).start();
  58. //防止客户端关闭 服务端接收不了 socket 写个while()
  59. while (true){
  60. Scanner sc = new Scanner(System.in);
  61. String str= sc.nextLine();
  62. outputStream.write(str.getBytes());
  63. }
  64. }
  65. }
  66. class client2{
  67. public static void main(String[] args) throws IOException {
  68. Socket socket = new Socket("127.0.0.1",7777);
  69. OutputStream outputStream = socket.getOutputStream();
  70. new Thread(new clientThread(socket)).start();
  71. //防止客户端关闭 服务端接收不了 socket 写个while()
  72. while (true){
  73. Scanner sc = new Scanner(System.in);
  74. String str= sc.nextLine();
  75. outputStream.write(str.getBytes());
  76. }
  77. }
  78. }
  79. class client3{
  80. public static void main(String[] args) throws IOException {
  81. Socket socket = new Socket("127.0.0.1",7777);
  82. OutputStream outputStream = socket.getOutputStream();
  83. new Thread(new clientThread(socket)).start();
  84. //防止客户端关闭 服务端接收不了 socket 写个while()
  85. while (true){
  86. Scanner sc = new Scanner(System.in);
  87. String str= sc.nextLine();
  88. outputStream.write(str.getBytes());
  89. }
  90. }
  91. }
  92. class clientThread implements Runnable{
  93. private Socket socket;
  94. public clientThread(Socket socket) {
  95. this.socket = socket;
  96. }
  97. @Override
  98. public void run() {
  99. try {
  100. InputStream is = socket.getInputStream();
  101. byte[] bs = new byte[1024];
  102. int len;
  103. while ((len = is.read(bs))>0){
  104. String msg = new String(bs,0,len);
  105. System.out.println(msg);
  106. }
  107. } catch (IOException e) {
  108. e.printStackTrace();
  109. }
  110. }
  111. }

案例:

客户端与服务端 形成翻译软件类型

  1. package cidian;
  2. import java.io.*;
  3. import java.net.ServerSocket;
  4. import java.net.Socket;
  5. import java.util.Properties;
  6. import java.io.IOException;
  7. import java.io.InputStream;
  8. import java.io.PrintStream;
  9. import java.net.Socket;
  10. import java.util.Scanner;
  11. //客户端
  12. class client {
  13. public static void main(String[] args) throws IOException {
  14. Socket socket = new Socket("127.0.0.1",2345);
  15. Scanner sc = new Scanner(System.in);
  16. System.out.println("请输入单词:");
  17. String filename = sc.next();
  18. PrintStream ps = new PrintStream(socket.getOutputStream());
  19. ps.println(filename);
  20. InputStream is = socket.getInputStream();
  21. byte[] bs = new byte[1024];
  22. int len;
  23. while((len=is.read(bs))>0){
  24. String msg = new String(bs,0,len);
  25. System.out.println(msg);
  26. }
  27. System.out.println("传输完毕");
  28. }
  29. }
  30. //服务器端
  31. public class server {
  32. public static void main(String[] args) throws IOException {
  33. ServerSocket serverSocket = new ServerSocket(2345);
  34. while (true){
  35. System.out.println("等待连接......");
  36. Socket socket = serverSocket.accept();
  37. new Thread(new serverThread(socket)).start();
  38. }
  39. //接受客户端发的文件名
  40. }
  41. }
  42. class serverThread implements Runnable{
  43. private Socket socket;
  44. public serverThread(Socket socket) {
  45. this.socket = socket;
  46. }
  47. @Override
  48. public void run() {
  49. try {
  50. //读到单词
  51. BufferedReader bf = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  52. String keywords = bf.readLine();
  53. Properties properties = new Properties();
  54. properties.load(new FileReader("C:\\Users\\杨嘿嘿\\.IntelliJIdea2019.3\\config\\scratches\\words.properties"));
  55. String value = properties.getProperty(keywords);
  56. if (value!=null){
  57. socket.getOutputStream().write(value.getBytes());
  58. }else {
  59. socket.getOutputStream().write("词典里面没有这个词".getBytes());
  60. }
  61. } catch (IOException e) {
  62. e.printStackTrace();
  63. }
  64. }
  65. }

作业:

客户端输入一个文件名 服务端接受 然后查找本地有没有这个文件 有的话 就把文件返回给客户端
//服务端

  1. package net4;
  2. import java.io.*;
  3. import java.net.ServerSocket;
  4. import java.net.Socket;
  5. import java.util.ArrayList;
  6. import java.util.Arrays;
  7. public class server {
  8. public static void main(String[] args) throws IOException {
  9. ServerSocket serverSocket = new ServerSocket(2345);
  10. while (true){
  11. System.out.println("等待连接......");
  12. Socket socket = serverSocket.accept();
  13. new Thread(new serverThread(socket)).start();
  14. }
  15. //接受客户端发的文件名
  16. }
  17. }
  18. class serverThread implements Runnable{
  19. private Socket socket;
  20. public serverThread(Socket socket) {
  21. this.socket = socket;
  22. }
  23. @Override
  24. public void run() {
  25. try {
  26. File file = new File("C:\\Users\\杨嘿嘿\\Desktop");
  27. BufferedReader bf = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  28. //读出文件名
  29. String filename = bf.readLine();
  30. //获取文件夹下的文件名数组
  31. String[] list = file.list();
  32. //将它转为list
  33. ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(list)) ;
  34. if (arrayList.contains(filename)){
  35. FileInputStream fis = new FileInputStream("C:\\Users\\杨嘿嘿\\Desktop\\"+filename);
  36. byte[] bs = new byte[2048];
  37. int len;
  38. while ((len=fis.read(bs))>0){
  39. socket.getOutputStream().write(bs,0,len);
  40. }
  41. System.out.println("传输完毕");
  42. socket.close();
  43. }
  44. } catch (IOException e) {
  45. e.printStackTrace();
  46. }
  47. }
  48. }

//客户端

  1. package net4;
  2. import java.io.*;
  3. import java.net.Socket;
  4. import java.util.Scanner;
  5. public class client {
  6. public static void main(String[] args) throws IOException {
  7. Socket socket = new Socket("127.0.0.1",2345);
  8. Scanner sc = new Scanner(System.in);
  9. System.out.println("请输入文件名:");
  10. String filename = sc.next();
  11. PrintStream ps = new PrintStream(socket.getOutputStream());
  12. ps.println(filename);
  13. InputStream is = socket.getInputStream();
  14. FileOutputStream ous = new FileOutputStream("server_"+filename);
  15. byte[] bs = new byte[1024];
  16. int len;
  17. while((len=is.read(bs))>0){
  18. ous.write(bs,0,len);
  19. }
  20. System.out.println("传输完毕");
  21. ous.close();
  22. }
  23. }