Java网络编程笔记
1.1、网络通信的要素:
如何实现网络的通信?
需要通信双方的地址:
-
IP
-
规则:网络通信的协议
TCP/IP参考模型:
小结:
-
网络编程中有两个主要的问题:
-
如何定位到网络上一台或多态主机?
-
找到主机之后如何进行通信?
-
-
网络编程中的要素
-
IP和端口号
-
网络通信协议:UDP、TCP
-
-
万物皆对象
1.2、IP
-
Java中的IP类:InetAddress;
-
IP地址的分类:
-
公网
-
私网
-
-
ipv4/ipv6
-
ipv4(格式:127.0.0.1):由4个字节组成,范围0~255,一共有大约42亿,30亿在北美,4亿在亚洲,2011年就用尽了;
-
ipv6(格式:fe80::7def:75c4:3651:ce22%15):
-
package com.zq.ip;
import java.net.InetAddress;
import java.net.UnknownHostException;
//测试ip
public class TestIp {
public static void main(String[] args) throws UnknownHostException {
//获取本机地址
InetAddress localhost1 = InetAddress.getByName("127.0.0.1");
InetAddress localhost2 = InetAddress.getByName("localhost");
InetAddress localhost3 = InetAddress.getLocalHost();
System.out.println(localhost1);
System.out.println(localhost2);
System.out.println(localhost3);
//查询网址ip地址
InetAddress baidu = InetAddress.getByName("www.baidu.com");
System.out.println(baidu);
}
}
1.3、端口
每个进程都会有一个端口
-
不同进程有不同端口号,用来区分软件
-
被规定为0~65535(TCP、UDP各有65535个)
-
多个协议下,不同的协议可以用相同的端口
-
端口分类
-
公有端口0~1023
-
http默认端口:80
-
https默认端口:443
-
ftp默认端口:21
-
-
程序注册端口1024~49151
-
Tomcat:8080
-
MySQL:3306
-
Oracle:1521
-
-
动态私有端口:49152~65535
-
-
1.4、通信协议
TCP/IP协议:
重要:
-
TCP:用户传输协议
-
UDP:用户数据报协议
TCP与UDP的对比:
-
TCP:打电话
-
连接,稳定
-
三次握手
,四次挥手
三次握手:最少需要三次,保证稳定连接!
A:你瞅啥?
B:瞅你咋地?
A:干一场?
四次挥手:
A:我要断开了!
B:你真的要断开了吗?
B:你真的真的要断开了吗?
A:我真的要断开了!
-
客户端与服务端
-
传输完成,释放连接,效率低
-
-
UDP:发短信
-
不连接,不稳定
-
客户端,服务端没有明确的界限
-
不管有没有准备好都能发给你
-
1.6、TCP实现通讯
-
服务端
package com.zq.tcp;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
//tcp协议服务端
public class TestTcpServer {
public static void main(String[] args) {
ServerSocket server = null;
Socket accept = null;
InputStream is = null;
ByteArrayOutputStream baos = null;
while (true) {
try {
//1.首先得有一个地址
server = new ServerSocket(8888);
//2.等待连接客户端
accept = server.accept();
//3.获取客户端发过来的信息
is = accept.getInputStream();
baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = is.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
//打印输出
System.out.println(baos.toString());
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源
if (baos != null) {
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (accept != null) {
try {
accept.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (server != null) {
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
-
客户端
package com.zq.tcp;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
//tcp协议客户端
public class TestTcpClient {
public static void main(String[] args) {
Socket socket = null;
OutputStream os = null;
Scanner scanner = null;
try {
//1.首先得有对方的ip地址和端口
InetAddress address = InetAddress.getByName("127.0.0.1");
int port = 8888;
//进行连接
socket = new Socket(address, port);
//发送消息
os = socket.getOutputStream();
os.write("Hello,World! 你好,世界!".getBytes());
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
1.5、UDP
发送端:
package com.zq.udp;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class TestUdpClient {
public static void main(String[] args) throws Exception {
//1.建立一个socket
DatagramSocket socket = new DatagramSocket(8888);
//2.需要一个包
String message = "Hello,World!";
InetAddress address = InetAddress.getByName("127.0.0.1");
DatagramPacket packet = new DatagramPacket(message.getBytes(), 0, message.getBytes().length, address, 9999);
//3.发送这个包
socket.send(packet);
//4.关闭连接
socket.close();
}
}
接收端:
package com.zq.udp;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class TestUdpServer {
public static void main(String[] args) throws Exception{
//1.建立一个socket
DatagramSocket socket = new DatagramSocket(9999);
//2.需要一个包
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data,0, data.length);
//3.接收发过来的包
socket.receive(packet);
//4.打印输出
System.out.println("来自ip为" + packet.getAddress() + "发来的消息");
String str = new String(packet.getData(),0,packet.getLength());
System.out.println(str);
//5.关闭连接
socket.close();
}
}
1.6、UDP实现聊天
-
创建发送消息的线程
package com.zq.chat;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
public class UdpSend implements Runnable{
private String username;
private String address;
private int toPort;
private DatagramSocket socket;
private BufferedReader bw;
public UdpSend(String username, int fromPort, String address, int toPort){
this.username = username;
this.address = address;
this.toPort = toPort;
try {
socket = new DatagramSocket(fromPort);
bw = new BufferedReader(new InputStreamReader(System.in));
} catch (Exception e){
e.printStackTrace();
}
}
@Override
public void run(){
while (true) {
try {
//发送消息
String message = username + ":" + bw.readLine();
DatagramPacket packet = new DatagramPacket(message.getBytes(), 0, message.getBytes().length, new InetSocketAddress(this.address, this.toPort));
socket.send(packet);
if(message.indexOf("bye") != -1)
break;
} catch (IOException e) {
e.printStackTrace();
}
}
//关闭资源
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
socket.close();
}
}
-
创建接收消息的线程
package com.zq.chat;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
/**
* @author Mr.zhou
* @version 1.0
* @date 2021/3/3 20:53
*/
public class UdpReceive implements Runnable {
private DatagramSocket socket;
public UdpReceive(int port){
try {
socket = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
try {
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, 0, data.length);
//阻塞式接收
socket.receive(packet);
String message = new String(packet.getData(), 0, packet.getLength());
System.out.println(message);
//如果接收到bye,则关闭
if (message.indexOf("bye") != -1)
break;
} catch (IOException e) {
e.printStackTrace();
}
}
//关闭资源
socket.close();
}
}
-
模拟学生并创建两个线程
package com.zq.chat;
import java.net.InetAddress;
/**
* @author Mr.zhou
* @version 1.0
* @date 2021/3/3 21:08
*/
public class ChatStudent {
public static void main(String[] args) {
new Thread(new UdpSend("Student", 6666, "localhost", 8888)).start();
new Thread(new UdpReceive(9999)).start();
}
}
-
模拟老师并创建两个线程
package com.zq.chat; /** * @author Mr.zhou * @version 1.0 * @date 2021/3/3 21:08 */ public class ChatTeacher { public static void main(String[] args) { new Thread(new UdpSend("Teacher", 7777, "localhost", 9999)).start(); new Thread(new UdpReceive(8888)).start(); } }
-
启动两个类,模拟对话如下:
你好,teacher Teacher:你好,Student
Student:你好,eacher 你好,Student
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用