网络多线程-基础知识
一、TCP字节流
要求:客户端发送一条消息,服务端接收并打印出来
思路:服务端要先监听某个端口,等待客户端的连接(处于阻塞状态);客户端需要知道自己是跟谁通信,要知道对方的IP及端口号,
客户端发送肯定就是把消息输出,用OutputStram
服务端是接收发送来的信息,用 InputStram
注意:要先启动服务端,自己家的大门都没打开,客人怎么可能进得去
client
public class SocketTCPClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
OutputStream outputStream = socket.getOutputStream();
outputStream.write("你好啊".getBytes());
socket.close();
outputStream.close();
}
}
Server
public class SocketTCPServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(9999); //端口号可以随意,1024下是系统都使用过了,1024-65535可以使用(不能使用被占用的)
System.out.println("服务端在9999端口等待连接");
Socket socket = serverSocket.accept();
System.out.println("连接成功");
InputStream inputStream = socket.getInputStream();
byte[] buf = new byte[1024];
int len = 0;
while((len=inputStream.read(buf)) != -1) {
System.out.println(new String(buf,0,len));
}
socket.close();
inputStream.close();
}
}
ServerSocket.accept()
是监听9999端口,有人是否连接。当然访问服务器的不止一个,每个连接都是独立的
Scoket s1 = serverSocket.accept();
Scoket s2 = serverSocket.accept();
Scoket s3 = serverSocket.accept();
如果在上一个的基础上,服务端接收到客户端的数据后,返回给客户端一条信息,并打印出来。
如果只是在服务端添加socket.getOutputStream()
,客户端添加socket.getInputStream
的话,启动后服务端就会一直处于读取状态,客户端也会一直在读取状态,没有结束的标记。双方都在等待对方说话,也不知道是不是说完了。
可以write完成后使用socket.shutDownOutPut()
来标记已经发送结束了
二、字符流
在idea中输入socket. 会显示所有方法,但是我们发现只能获取字节流对象,所有要用到IO中的 InputStreamReader
和OuputStreamWriter
进行转换
发送后,插入换行符,并手动刷新
Client
public class SocketTCPClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
OutputStream outputStream = socket.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write("你好啊,服务器");
bufferedWriter.newLine(); //插入换行符,代表写入的内容结束
bufferedWriter.flush(); //需要手动刷新,否则无法写入数据管道
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
System.out.println(bufferedReader.readLine());
bufferedReader.close();
bufferedWriter.close();
socket.close();
}
}
Server
public class SocketTCP01Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务端在9999端口等待连接");
Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
System.out.println(bufferedReader.readLine());
OutputStream outputStream = socket.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write("我在回应你,客户端");
bufferedWriter.newLine();
bufferedWriter.flush();
bufferedWriter.close();
socket.close();
inputStream.close();
serverSocket.close();
}
}
UDP网络通信原理
类 DatagramSocket
和 DatagramPacket
实现了基于UDP协议网络程序,UDP数据报通过数据报套接字 DatagramSocket 发送和接收,系统不保证UDP数据包一定能够安全到达目的地,也不确定什么时候可以抵达。DatagramPacket对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号。
基本流程
- 核心的两个类/对象 DatagramSocket和DatagramPacket
- 建立发送端、接收端
- 建立数据包
- 调用DatagramSocket的发送和接收
- 关闭DatagramSocket
程序A
public class UDPA {
public static void main(String[] args) throws IOException {
//给小B发信息
DatagramSocket datagramSocket = new DatagramSocket(7777);
byte[] bytes = "你好啊,小B".getBytes();
DatagramPacket datagramPacket = new DatagramPacket(bytes,bytes.length, InetAddress.getLocalHost(),8888); //后两个参数是对方的地址和端口
datagramSocket.send(datagramPacket);
//接收小B回来的信息
datagramSocket.receive(datagramPacket);
int length = datagramPacket.getLength();
byte[] data = datagramPacket.getData();
System.out.println(new String(data,0,length));
datagramSocket.close();
}
}
程序B
public class UDPB {
public static void main(String[] args) throws IOException {
DatagramSocket datagramSocket = new DatagramSocket(8888);
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf,buf.length);
//等待数据
//将接收到的包填充到 packet
datagramSocket.receive(packet);
//将 packet进行拆包,取出数据
byte[] data = packet.getData();
//取出数据实际长度
int length = packet.getLength();
System.out.println(new String(data,0,length));
//给小A回信息
packet.setAddress(InetAddress.getLocalHost()); //设置对方地址
packet.setPort(7777); // 设置对方端口
byte[] bytes = "你好,小A".getBytes();
packet.setData(bytes,0,bytes.length);
datagramSocket.send(packet);
datagramSocket.close();
}
}
注意:要先启动B,再启动A,不然就会阻塞,如果先启动A,A给B发消息,B还未启动,相当于无效,后面启动B时,B就一直在第一步的等待A数据,A就处于第二步的等待B数据
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器