网络编程
网络编程笔记
1.1、概述
网络编程是指编写程序使不同设备(如电脑、手机)通过网络(局域网/互联网)进行数据传输、通信的技术。
核心目的:实现跨设备的数据交互,常见场景如文件传输、即时通讯、网页请求等。
1.2、网络通信的要素
实现网络通信必须具备3个核心要素:
- IP地址:设备在网络中的唯一标识(相当于“家庭住址”)。
- 端口号:设备中程序的唯一标识(相当于“家庭里的房间号”)。
- 通信协议:设备间数据传输的规则(相当于“交流的语言”)。
1.3、IP
- 定义:Internet Protocol(互联网协议),是分配给网络设备的数字标签(如
192.168.1.1)。 - 分类:
- IPv4:32位二进制,格式为
xxx.xxx.xxx.xxx(如127.0.0.1是本地回环地址,代表本机)。 - IPv6:128位二进制,解决IPv4地址不足的问题(格式为8组16进制数,如
2001:0db8:85a3:0000:0000:8a2e:0370:7334)。
- IPv4:32位二进制,格式为
- 常用命令:
- Windows:
ipconfig(查看本机IP)。 - Linux/macOS:
ifconfig或ip addr。
- Windows:
1.4、端口
- 定义:设备中程序的唯一编号(范围:
0~65535),用于区分同一设备上的不同应用。 - 分类:
- 知名端口(
0~1023):系统/常用服务占用(如HTTP的80端口、HTTPS的443端口)。 - 动态端口(
1024~65535):普通程序可使用的端口(编程时建议用1024之后的端口,避免冲突)。
- 知名端口(
- 注意:同一设备上,一个端口同一时间只能被一个程序占用。
1.5、通信协议
- 定义:设备间数据传输的规则、格式约定,确保双方能“读懂”对方的数据。
- 常见协议:
- TCP:可靠的、面向连接的协议(如文件传输、HTTP请求),传输前需建立“三次握手”,传输后需“四次挥手”断开连接。
- UDP:不可靠的、无连接的协议(如即时通讯、视频通话),速度快但可能丢包。
- HTTP/HTTPS:应用层协议,基于TCP,用于网页数据传输(HTTPS是加密的HTTP)。
1.6、TCP
-
核心特点:可靠、面向连接、传输效率略低。
-
连接建立:三次握手(像打电话确认对方能听到)
通俗流程:- 客户端→服务端:“喂,你能听到吗?”(发送SYN包,请求建立连接)
- 服务端→客户端:“能听到,你能听到我吗?”(回复SYN+ACK包,确认请求+请求自己的连接)
- 客户端→服务端:“能听到,那咱开始聊吧!”(回复ACK包,确认对方的连接)
公式标记:SYN → SYN+ACK → ACK
作用:确保双方“收发能力都正常”,避免无效连接。
-
连接断开:四次挥手(像挂电话前确认对方说完了)
通俗流程:- 客户端→服务端:“我说完了,准备挂了”(发送FIN包,请求断开)
- 服务端→客户端:“好的,我知道了”(回复ACK包,确认请求)
- 服务端→客户端:“我也说完了,你可以挂了”(发送FIN包,自己的内容发完了)
- 客户端→服务端:“收到,那我挂了”(回复ACK包,确认断开)
公式标记:FIN → ACK → FIN → ACK
作用:确保双方“数据都发完了”,避免丢数据。
-
典型场景:文件上传
流程:-
客户端通过IP+端口连接服务端(三次握手建立连接)。
-
客户端读取本地文件,通过输出流将文件数据发送给服务端。
-
服务端通过输入流接收数据,用文件输出流保存到本地。
-
传输完成后,双方通过“四次挥手”断开连接。
客户端向服务端传输文件示例
-
客户端代码
package com.thomas.lesson02;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class TcpClientDemo01 {
public static void main(String[] args) {
Socket socket = null;
OutputStream outputStream = null;
try {
//1.要知道服务器的地址端口号
InetAddress serverIP = InetAddress.getByName("127.0.0.1");
int serverPort = 9999;
//2.创建一个socket连接
socket = new Socket(serverIP,serverPort);
//3.发送信息,IO流
outputStream = socket.getOutputStream();
if (outputStream != null) {
outputStream.write("你好".getBytes());
}else {
System.out.println("连接失败,输出流为空");
}
} catch (Exception e) {
throw new RuntimeException(e);
}finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
}catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
服务端
package com.thomas.lesson02;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServerDemo01 {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream inputStream = null;
ByteArrayOutputStream baos = null;
try {
//1.有一个地址
serverSocket = new ServerSocket(9999);
//2.等待客户链接过来
socket = serverSocket.accept();
//3.读取客户端的信息
inputStream = socket.getInputStream();
//管道流
baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.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) {}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
服务端向客户端发送传输完毕信息
部分不重叠代码-客户端
//通知服务器传输完毕
socket.shutdownOutput();
//确定服务器接收完毕
InputStream is = socket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] b2 = new byte[1024];
int len2;
while ((len2=is.read(b2))!=-1) {
baos.write(b2,0,len2);
}
String receivedMsg = baos.toString();
System.out.println(receivedMsg);
服务端
//告诉客户端发送完毕
outputStream = socket.getOutputStream();
outputStream.write("ok,收到".getBytes());
用DataOutputStream的writeUTF方法传输字符串与转为字节的相比
客户端
package com.thomas.test;
import java.io.*;
import java.net.Socket;
/*
* 千万千万记得关闭资源
*/
public class TcpClient {
public static void main(String[] args) throws IOException {
//建立socket
Socket socket = new Socket("127.0.0.1",8080);
//输出流,作为发送方,建立输出管道
OutputStream outputStream = socket.getOutputStream();
//输入流,从本地获取文件
FileInputStream fis = new FileInputStream("day02.md");
//输出文件
int len;
//字节型数组缓冲区
byte[] b = new byte[1024];
while ((len=fis.read(b))!=-1) {
//输出流写文件
outputStream.write(b,0,len);
}
socket.shutdownOutput();
fis.close();
//使用readUTF方法读取
DataInputStream dis = new DataInputStream(socket.getInputStream());
//创建字符串对象存储读取字符串
String str = dis.readUTF();
System.out.println(str);
dis.close();
outputStream.close();
socket.close();
}
}
1.7、UDP
发送短信,不需要连接
发送消息
发送端
package com.thomas.lesson03;
import java.io.IOException;
import java.net.*;
public class UdpClientDemo01 {
public static void main(String[] args) throws IOException {
//1.建立socket
DatagramSocket socket = new DatagramSocket();
//2.建立包
String msg = "你好,服务器";
//发送给谁
InetAddress address = InetAddress.getByName("127.0.0.1");
int port = 9090;
DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0,msg.getBytes().length,address,port);
//3.发送包
socket.send(packet);
//4.关闭流
socket.close();
}
}
接收端
package com.thomas.lesson03;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class UdpServerDemo01 {
public static void main(String[] args) throws Exception {
//socket
DatagramSocket socket = new DatagramSocket(9090);
//接收包
byte[] buf = new byte[1024];
//packet
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
System.out.println(new String(packet.getData(),0,packet.getLength()));
//关流
socket.close();
}
}

浙公网安备 33010602011771号