《J2SE 回炉再造17》-------溺水狗

本文深入讲解网络编程核心概念,包括网络通信协议、IP协议、TCP/UDP协议、Socket编程及其实例,涵盖数据分层、封装与拆封,子网掩码与网关解析,适合初学者与进阶开发者。

第十一章 网络编程

1. 提纲
值得注意的是网络编程不等同于网站编程
在这里插入图片描述
在这里插入图片描述
2. 网络基础概念
在这里插入图片描述
3. 网络通信协议及接口
在这里插入图片描述
4. 数据分层的思想
在这里插入图片描述
在这里插入图片描述
5. 数据封装和数据拆封
在这里插入图片描述
在这里插入图片描述
6. IP协议
在这里插入图片描述
IPV4协议中用4个字节表示IP地址,故每位的值最大不超过255。
IP由网络段+主机段两部分组成 ;又根据网络段所占字节数分为:A类网(1个字节)、B类网(2个字节)、C类网(3个字节)等。
子网掩码(subnet mask)又叫网络掩码、地址掩码、子网络遮罩,它是一种用来指明一个IP地址的哪些位标识的是主机所在的子网,以及哪些位标识的是主机的位掩码。子网掩码不能单独存在,它必须结合IP地址一起使用。子网掩码只有一个作用,就是将某个IP地址划分成网络地址和主机地址两部分。
网关(Gateway)又称网间连接器、协议转换器。默认网关在网络层上以实现网络互连,是最复杂的网络互连设备,仅用于两个高层协议不同的网络互连。网关的结构也和路由器类似,不同的是互连层。网关既可以用于广域网互连,也可以用于局域网互连。
根据子网掩码判断主机是否在一个网络上
子网掩码详解

7. TCP/UDP协议
在这里插入图片描述
TCP可靠但是慢,UDP不可靠但是快;如CF游戏射击子弹时是使用的就是UDP协议,因为可以丢包(对方卡了)。

8. Socket协议

  • TCP协议
    在这里插入图片描述
    在这里插入图片描述
  • 端口号占两个字节最多65536个,而端口号也分TCP和UDP两种。自己编写程序时用1024以上的端口号,1024以下的端口号系统随时征用。
  • TCP上的服务端(server端)使用ServerSocket,客户端(client端)使用Socket。程序成对出现。程序启动时要先启动Server端再启动Client端。

例子1(服务器端):

import java.net.*;
import java.io.*;

public class TestServer {
	public static void main(String[] args) {
		try{
			ServerSocket ss = new ServerSocket(8888);  //服务器端8888接口用来与某个客户端进行互访
			while(true) {      //死循环保证服务器端时刻准备连接,不会宕机
				Socket s = ss.accept();  //accept()方法与客户端实现连接
				OutputStream os = s.getOutputStream();  //获取服务器端的输出流
				DataOutputStream dos = new DataOutputStream(os);  //进行包装
				dos.writeUTF("Hello," + s.getInetAddress()   //输出流里写入
				+ "port#" + s.getPort() + " bye-bye!!");
				dos.close();  //关闭数据流
				s.close();    //关闭套接字
			}
		} catch(IOException e) {
			e.printStackTrace();
			System.out.println("Program is ERROR" + e);
		}
		
	}
}

例子1(客户端):

import java.net.*;
import java.io.*;

public class TestClient {
	public static void main (String[] args) {
		try {
			Socket s = new Socket("127.0.0.1",8888); //设置服务端地址,及客户端与服务端连接的端口号
			InputStream is = s.getInputStream();   //获取客户端输入流
			DataInputStream dis = new DataInputStream(is);   //包装输入流
			System.out.println(dis.readUTF());   //读取输入流的内容
			dis.close();  //关闭输入流
			s.close();  //关闭套接字
		} catch(ConnectException ce) {
			ce.printStackTrace();
			System.out.println("Server Connect is ERROR");
		} catch(IOException e) {
			e.printStackTrace();
		}
	}	
}

例子2(服务器端):

import java.net.*;
import java.io.*;

public class TestSocketServer {
	public static void main(String[] args){
		try {
			ServerSocket ss = new ServerSocket(5888);
			Socket socket = ss.accept();
			InputStream is = socket.getInputStream();
			OutputStream os = socket.getOutputStream();
			DataInputStream dis = new DataInputStream(is);
			DataOutputStream dos = new DataOutputStream(os);
			String s = null;
			if((s=dis.readUTF())!= null) {
				System.out.println(s);
				System.out.println("Form:" + socket.getInetAddress());
				System.out.println("Port:" + socket.getPort());
			}
			dos.writeUTF("hi,hello");
			dis.close();
			dos.close();
			socket.close();
		} catch(IOException e) {
			e.printStackTrace();
		}
	}
}

例子2(客户端):

import java.net.*;
import java.io.*;

public class TestSocketClient {
	public static void main(String[] args) {
		try {
			Socket socket = new Socket("127.0.0.1",5888);
			InputStream is = socket.getInputStream();
			OutputStream os = socket.getOutputStream();
			DataInputStream dis = new DataInputStream(is);
			DataOutputStream dos = new DataOutputStream(os);
			dos.writeUTF("hi");
			String s = null;
			if((s=dis.readUTF()) != null) {
				System.out.println(s);
			}
			dos.close();
			dis.close();
			socket.close();
		} catch(UnknownHostException e) {
			e.printStackTrace();
		} catch(IOException e) {
			e.printStackTrace();
		}
	}
}

例子3(服务器端):

import java.io.*;
import java.net.*;

public class TestTalkServer {
	public static void main(String[] args) {
		try {
			ServerSocket ss = new ServerSocket(6688);
			Socket socket = ss.accept();
			BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			PrintWriter pw = new PrintWriter(socket.getOutputStream());
			BufferedReader brs = new BufferedReader(new InputStreamReader(System.in));
			System.out.println("Client:" + br.readLine());
			if(br.readLine()== null) {
				System.out.println("Clinet exit Connection!!");
				br.close();
				brs.close();
				pw.close();
				socket.close();
				ss.close();
			} else{
				String s = brs.readLine();
				while(!s.equals("bye")) {
				pw.println(s);
				pw.flush();
				System.out.println("Server:" + s);
				System.out.println("Client:" + br.readLine());
				s = brs.readLine();
				}
				br.close();
				brs.close();
				pw.close();
				socket.close();
				ss.close();
			}
			
		} catch(IOException e) {
			System.out.println("ERROR");
			e.printStackTrace();
		}
	}
}

例子3(客户端):

import java.io.*;
import java.net.*;

public class TestTalkClient {
	public static void main(String[] args) {
		try {
			Socket socket = new Socket("127.0.0.1",6688);
			BufferedReader brs = new BufferedReader(new InputStreamReader(System.in));
			PrintWriter pw = new PrintWriter(socket.getOutputStream());
			BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			String s = brs.readLine();
			while (!s.equals("bye")) {
				pw.println(s);
				pw.flush();
				System.out.println("Client:" + s);
				System.out.println("Server:" + br.readLine());
				s = brs.readLine();
			}
			pw.close();
			br.close();
			brs.close();
			socket.close();
		} catch(IOException e) {
			System.out.println("ERROR");
			e.printStackTrace();
		}
	}
}
  • UDP协议
    在这里插入图片描述
    UDP协议在使用过程中没有实际意义上的ServerSocket和Socket,只存在逻辑意义上的。程序成对出现。

例子1(逻辑意义服务端):

import java.net.*;

public class TestUDPServer {
	public static void main(String[] args) {
		try {
			byte[] buf = new byte[1024];   //创建一个大小为1024的字符数组,用来装接受来的数据。
			DatagramPacket dp = new DatagramPacket(buf,buf.length); //将数据打成数据包。
			DatagramSocket ds = new DatagramSocket(8866);  //用8866端口接收数据
			while(true) {     //死循环,无限循环
				ds.receive(dp);   //接收传过来的数据包
				System.out.println(new String(buf,0,dp.getLength()));  //屏幕输出
			}
		} catch(Exception e) {
			System.out.println("ERROR");
			e.printStackTrace();
		}
		
	}
}

例子1(逻辑意义客户端):

import java.net.*;

public class TestUDPClient {
	public static void main(String[] args) {
		try {
			byte[] buf = (new String("Hello")).getBytes();  //将字符串转换成字符数组
			DatagramPacket dp = new DatagramPacket(buf,buf.length,new InetSocketAddress("127.0.0.1",8866));   //将数据打成数据包向本机的8866端口传送
			DatagramSocket ds = new DatagramSocket(9999);  //由9999端口送出
			ds.send(dp); //发送数据包
			ds.close();
		} catch(Exception e) {
			System.out.println("ERROR");
			e.printStackTrace();
		}
		
	}
}

例子2(如何传送一个long类型的数字)(逻辑意义服务器端):

import java.net.*;
import java.io.*;

public class TestUDPLongServer {
	public static void main(String[] args) {
		try {
			byte[] buf = new byte[1024];
			DatagramPacket dp = new DatagramPacket(buf,buf.length);
			DatagramSocket ds = new DatagramSocket(5678);
			while(true) {
				ds.receive(dp);
				ByteArrayInputStream bais = new ByteArrayInputStream(buf);
				DataInputStream dis = new DataInputStream(bais);
				System.out.println(dis.readLong());
			}
		} catch(Exception e) {
			System.out.println("ERROR");
		}
		
	}
}

例子2(如何传送一个long类型的数字)(逻辑意义客户端):

import java.io.*;
import java.net.*;

public class TestUDPLongClient {
	public static void main(String[] args) {
		try{
		long l = 10000L;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		DataOutputStream dos = new DataOutputStream(baos);
		dos.writeLong(l);
			byte[] buf = baos.toByteArray(); //toByteArray()创造一个输出流大小内容相同的字符数组
			System.out.println(buf.length);
			DatagramPacket dp = new DatagramPacket(buf,buf.length,new InetSocketAddress("127.0.0.1",5678));
			DatagramSocket ds = new DatagramSocket(9999);
			ds.send(dp);
			ds.close();
		} catch(Exception e) {
			System.out.println("ERROR");
		}
		
	}
}

9. 总结
在这里插入图片描述
注:本博客由溺水狗原创但其学习资源资料来源于网络(马士兵老师的教学视频),特此感谢马士兵老师

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值