Java语言基础--网络编程
Java语言基础--网络编程
InetAddress
表示主机的地址信息的类
- 获取本机InetAddress对象getLocalHost
- 根据指定主机名/域名获取IP地址对象getByName
- 获取InetAddress对象的主机名getHostName
- 获取InetAddress对象的地址getHostAddress
Socket
套接字(socket)开发网络应用程序被广泛采用,以至于成为事实上的标准,通信两端都要有Socket作为端点,网络通信就是端点间的通信
socket允许程序把网络连接当作流,数据在两个Socket间通过IO传输;发起通信的程序是客服端,等待通信请求的为服务端
基于客户端-服务端的网络通信,底层使用TCP/IP协议
- TCP编程
- 使用Socket对象
- getOutputStream 写入发送数据
- shutdownOutput 写入结束标记;
- 当使用字符流写入时,可以使用write.newLine()设置结束标记,但是要求对方使用readLine()
- getInputStream 读取接收数据
- UDP编程
- 使用DatagramSocket对象和DatagramPacket【数据包/数据报】
- DatagramSocket指定哪个端口接收数据包
- DatagramPacket数据对象拆包/装包,数据包最大64K上限
代码案例
-
TCP编程-字节流
//服务端 public class SocketTcpServer{ public static void main(String[] args) throw IPException{ //监听本机9999端口 ServerSocket serverSocket = new ServerSocket(9999); //阻塞程序等待Socket对象创建,就是链接建立 Socket socket = serverSocket.accrpt(); //拿到链接的输入流 InputStream inputStream = socket.getInputStream(); //读取=接收数据 byte[] buf = new byte[1024]; int readLen = 0; while((readLen = inputStream.read())!=-1){ //直接输出到控制台 System.out.println(new String(buf,0,readLen)); } //拿到链接的输出流 OutputStream outputStream = socket.getOutputStream(); //写入=发送数据 outputStream.write("hello, Client".getBytes()); //写入结束标记 socket.shutdownOutput(); //关闭资源 inputStream.close(); socket.close(); serverSocket.close(); } } //客户端 public class SocketTCPClient{ public static void main(String[] args) throws IOException{ //链接目标主机程序,链接成功会创建Socket对象,这里是本机的9999端口 Socket socket = new Socket(InetAddress.getLocalHost(),9999); //拿到链接的输出流 OutputStream outputStream = socket.getOutputStream(); //写入=发送数据 outputStream.write("hello, server".getBytes()); //写入结束标记 socket.shutdownOutput(); //拿到链接的输入流 InputStream inputStream = socket.getInputStream(); //读取=接收数据 byte[] buf = new byte[1024]; int readLen = 0; while((readLen = inputStream.read())!=-1){ //直接输出到控制台 System.out.println(new String(buf,0,readLen)); } //关闭资源 outputStream.close(); socket.close(); } }
-
TCP编程-字符流
//服务端 public class SocketTcpServer{ public static void main(String[] args) throw IPException{ //监听本机9999端口 ServerSocket serverSocket = new ServerSocket(9999); //阻塞程序等待Socket对象创建,就是链接建立 Socket socket = serverSocket.accrpt(); //拿到链接的输入流 InputStream inputStream = socket.getInputStream(); //读取=接收数据 //这里使用转换流将字节转为字符流,同时放入到增强字符流对象中 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String s = bufferedReader.readLine(); System.out.println(s); //拿到链接的输出流 OutputStream outputStream = socket.getOutputStream(); //写入=发送数据 //这里使用转换流将字节转为字符流,同时放入到增强字符流对象中 BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream)); bufferedWriter.write("hello,server 字符流"); bufferedWriter.newLine();//写入结束标记,此时要求对方使用readLine来接收读取 bufferedWriter.flush();//使用字符流,需要使用此方法刷新写入,否则不会真正写入对象包含的节点流 //关闭资源 bufferedReader.close(); bufferedWriter.close(); socket.close(); serverSocket.close(); } } //客户端 public class SocketTCPClient{ public static void main(String[] args) throws IOException{ //链接目标主机程序,链接成功会创建Socket对象,这里是本机的9999端口 Socket socket = new Socket(InetAddress.getLocalHost(),9999); //拿到链接的输出流 OutputStream outputStream = socket.getOutputStream(); //写入=发送数据 //这里使用转换流将字节转为字符流,同时放入到增强字符流对象中 BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream)); bufferedWriter.write("hello,server 字符流"); bufferedWriter.newLine();//写入结束标记,此时要求对方使用readLine来接收读取 bufferedWriter.flush();//使用字符流,需要使用此方法刷新写入,否则不会真正写入对象包含的节点流 //拿到链接的输入流 InputStream inputStream = socket.getInputStream(); //读取=接收数据 //这里使用转换流将字节转为字符流,同时放入到增强字符流对象中 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String s = bufferedReader.readLine(); System.out.println(s); //关闭资源 bufferedReader.close(); bufferedWriter.close(); socket.close(); }
}
- TCP-文件传输
```java
public class TCPFileUploadServer {
public static void main(String[] args) throws IOException {
// 启动服务监听端口
ServerSocket serverSocket = new ServerSocket(9999);
// 等待连接
Socket socket = serverSocket.accept();
// 接收文件
InputStream inputStream = socket.getInputStream();
String filePath = "qie.png";
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath));
byte[] bytes = new byte[1024];
int bytesLen = 0;
while ((bytesLen=inputStream.read(bytes))!=-1){
bos.write(bytes,0,bytesLen);
}
//关闭资源
inputStream.close();
bos.close();
socket.close();
serverSocket.close();
}
public class TCPFileUploadClient {
public static void main(String[] args) throws IOException {
//客户端连接服务器
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
//准备发送数据
String filePath = "e:\\qie.png";
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
OutputStream os = socket.getOutputStream();
//发送
byte[] bytes = new byte[1024];
int bytesLen = 0;
while ((bytesLen = bis.read(bytes))!=-1){
os.write(bytes, 0, bytesLen);
}
//关闭资源
os.close();
bis.close();
socket.close();
}
}
工具类中间层
/**
* 此类用于演示关于流的读写方法
*
*/
public class StreamUtils {
/**
* 功能:将输入流转换成byte[]
* @param is
* @return
* @throws Exception
*/
public static byte[] streamToByteArray(InputStream is) throws Exception{
ByteArrayOutputStream bos = new ByteArrayOutputStream();//创建输出流对象
byte[] b = new byte[1024];
int len;
while((len=is.read(b))!=-1){
bos.write(b, 0, len);
}
byte[] array = bos.toByteArray();
bos.close();
return array;
}
/**
* 功能:将InputStream转换成String
* @param is
* @return
* @throws Exception
*/
public static String streamToString(InputStream is) throws Exception{
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder builder= new StringBuilder();
String line;
while((line=reader.readLine())!=null){ //当读取到 null时,就表示结束
builder.append(line+"\r\n");
}
return builder.toString();
}
}
/*
下面是客户端和服务端代码
*/
public class TCPFileUploadServer {
public static void main(String[] args) throws Exception {
//1. 服务端在本机监听8888端口
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("服务端在8888端口监听....");
//2. 等待连接
Socket socket = serverSocket.accept();
//3. 读取客户端发送的数据
// 通过Socket得到输入流
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
byte[] bytes = StreamUtils.streamToByteArray(bis);
//4. 将得到 bytes 数组,写入到指定的路径,就得到一个文件了
String destFilePath = "src\\abc.mp4";
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFilePath));
bos.write(bytes);
bos.close();
// 向客户端回复 "收到图片"
// 通过socket 获取到输出流(字符)
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
writer.write("收到图片");
writer.flush();//把内容刷新到数据通道
socket.shutdownOutput();//设置写入结束标记
//关闭其他资源
writer.close();
bis.close();
socket.close();
serverSocket.close();
}
}
public class TCPFileUploadClient {
public static void main(String[] args) throws Exception {
//客户端连接服务端 8888,得到Socket对象
Socket socket = new Socket(InetAddress.getLocalHost(), 8888);
//创建读取磁盘文件的输入流
//String filePath = "e:\\qie.png";
String filePath = "e:\\abc.mp4";
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
//bytes 就是filePath对应的字节数组
byte[] bytes = StreamUtils.streamToByteArray(bis);
//通过socket获取到输出流, 将bytes数据发送给服务端
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
bos.write(bytes);//将文件对应的字节数组的内容,写入到数据通道
bis.close();
socket.shutdownOutput();//设置写入数据的结束标记
//=====接收从服务端回复的消息=====
InputStream inputStream = socket.getInputStream();
//使用StreamUtils 的方法,直接将 inputStream 读取到的内容 转成字符串
String s = StreamUtils.streamToString(inputStream);
System.out.println(s);
//关闭相关的流
inputStream.close();
bos.close();
socket.close();
}
}
netstat指令(命令行)
-
参数-an 查看当前主机网络情况,包括端口监听
-
参数-an | more 可以分页显示
-
参数-anb 查看包含程序名的网络情况
冷知识:客户端连接到服务端,实际上客户端也通过一个端口和服务端进行通讯,这个端口是TCP/IP来随机分配
DatagramSocket
代码案例
public class UDPService {
public static void main(String[] args) throws IOException {
//建立入口
DatagramSocket socket = new DatagramSocket(9999);
//准备接收数据包
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
//等待接收数据
socket.receive(packet);
//输出数据(拆包)
String context = new String(packet.getData(), 0, packet.getLength());
System.out.println(context);
//准备发送数据包
byte[] contextByte = "没问题".getBytes();
DatagramPacket packetSend =
new DatagramPacket(contextByte,contextByte.length, InetAddress.getByName("192.168.1.18"), 9998);
//发送数据
socket.send(packetSend);
//关闭资源
socket.close();
}
}
public class UDPClient {
public static void main(String[] args) throws IOException {
//建立入口
DatagramSocket socket = new DatagramSocket(9998);
//准备发送数据包
byte[] contextByte = "今晚吃火锅!".getBytes();
DatagramPacket packet =
new DatagramPacket(contextByte,contextByte.length, InetAddress.getByName("192.168.1.18"), 9999);
//发送数据
socket.send(packet);
//准备接收数据包
byte[] bytes = new byte[1024];
DatagramPacket packetReceive = new DatagramPacket(bytes, bytes.length);
//等待接收数据
socket.receive(packetReceive);
//输出数据(拆包)
String context = new String(packetReceive.getData(), 0, packetReceive.getLength());
System.out.println(context);
//关闭资源
socket.close();
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?