第十六话-Java网络编程
IP
-
唯一定位一台网络上计算机
-
127.0.0.1 : 本机 :localhost
-
ip地址分类
- ipv4/ipv6
- ipv4:四个字节,一共42亿个
- ipv6:128位,8个无符号整数
- 公网(互联网)+私网(局域网)
- ABCD类地址
- 192.168.XX.XX,专门给组织内使用
-
域名:记忆IP问题
package com.xie.lessonip;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class TestInetAddress {
public static void main(String[] args) {
try {
//查询本机地址
InetAddress inetAddress1 = InetAddress.getByName("127.0.0.1");
System.out.println(inetAddress1);
InetAddress inetAddress2 = InetAddress.getByName("localhost");
System.out.println(inetAddress2);
InetAddress inetAddress3 = InetAddress.getLocalHost();
System.out.println(inetAddress3);
//查询网址地址
InetAddress inetAddress4 = InetAddress.getByName("www.baidu.com");
System.out.println(inetAddress4);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
端口
端口表示计算机上的一个程序的进程;
- 不同的进程有不同的端口号
- 规定范围0~65535
- TCP,UDP:65535*2 单个协议下,端口号不能冲突
- 端口分类
- 公有端口:0~1023
- HTTP:80
- HTTPS:443
- FTP:21
- Telnet:23
- 程序注册端口:1024~49151,分配用户或程序
- Tomcat:8080
- Mysql:3306
- Oracle:1521
- 动态、私有:49152~65535
- 公有端口:0~1023
//查看所有端口
netstat -ano
//查看具体端口
netstat -ano|findstr "5900"
//查看指定端口的进程
tasklist|findstr "8696"
package com.xie.lessonip;
import java.net.InetSocketAddress;
public class TestInetSocketAddress {
public static void main(String[] args) {
InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1",8080);
InetSocketAddress socketAddress2 = new InetSocketAddress("localhost",8080);
System.out.println(socketAddress);
System.out.println(socketAddress2);
System.out.println(socketAddress.getAddress());
System.out.println(socketAddress.getHostName());
System.out.println(socketAddress.getPort());
}
}
通信协议
TCP:用户传输协议
- 连接稳定、三次握手、四次挥手、客服端服务端,传输完成释放连接效率低
UDP:用户数据包协议
- 不连接不稳定,客户端服务端没有明确界限
TCP/IP协议簇:实际是一组协议
代码DEMO
客户端
package com.xie.lessonip;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
public class TcpClientDemo1 {
public static void main(String[] args){
Socket socket = null;
OutputStream os = null;
try {
//1 知道服务端ip端口
InetAddress ip = InetAddress.getByName("127.0.0.1");
int port = 9999;
//2 创建socket连接到服务端
socket = new Socket(ip, port);
//3 发送消息,IO流
os = socket.getOutputStream();
os.write("测试连接".getBytes());
} catch (Exception 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();
}
}
}
}
}
服务端
package com.xie.lessonip;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.*;
public class TcpServiceDemo1 {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
ByteArrayOutputStream baos = null;
try {
//1 创建服务端
serverSocket = new ServerSocket(9999);
while (true){
//2 等待客户端连接
socket = serverSocket.accept();
//3 获取输入流,读取客户端消息
is = socket.getInputStream();
//4 管道流,一次打印所有读取的内容
baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
//5 读取内容放到管道流,实际是字节数组
while ((len=is.read(buffer))!=-1){
baos.write(buffer,0,len);
}
//6 一次打印所有读取内容
System.out.println(baos.toString());
}
} catch (Exception 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(socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(serverSocket!=null){
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
TCP上传文件
客户端
package com.xie.lessonip;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
public class TcpClientDemo2 {
public static void main(String[] args) throws Exception {
//1 创建socket连接
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9999);
//2 创建输出流
OutputStream os = socket.getOutputStream();
//3 读取文件,写出文件
FileInputStream fis = new FileInputStream(new File("picture.png"));
byte[] buffer = new byte[1024];
int len;
while ((len=fis.read(buffer))!=-1){
os.write(buffer,0,len);
}
//通知服务器,已传送完毕
socket.shutdownOutput();
//接受服务器消息,确定服务器接收完毕,才能断开连接
InputStream inputStream = socket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer2 = new byte[1024];
int len2;
while ((len=inputStream.read(buffer))!=-1){
baos.write(buffer,0,len);
}
System.out.println(baos.toString());
//关闭资源
baos.close();
inputStream.close();
fis.close();
os.close();
socket.close();
}
}
服务端
package com.xie.lessonip;
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServiceDemo2 {
public static void main(String[] args) throws Exception {
// 1 创建服务
ServerSocket serverSocket = new ServerSocket(9999);
// 2 监听客户端连接
Socket socket = serverSocket.accept();
// 3 获取输入流
InputStream is = socket.getInputStream();
// 4 文件输出
FileOutputStream fos = new FileOutputStream(new File("receive.png"));
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer))!=-1){
fos.write(buffer);
}
// 通知客户端,我已接收完毕
OutputStream os = socket.getOutputStream();
os.write("我已接收完毕,你可以断开了".getBytes());
//关闭资源
os.close();
fos.close();
is.close();
socket.close();
serverSocket.close();
}
}
UDP
代码-控制台输入通信
发送端
package com.xie.chat;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
public class UdpSendDemo1 {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(6666);
//准备数据:控制台读取 System.in
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true){
String data = reader.readLine();
byte[] datas = data.getBytes();
DatagramPacket packet = new DatagramPacket(datas,0,datas.length,
new InetSocketAddress("localhost",8888));
socket.send(packet);
if(data.equals("bye")){
break;
}
}
socket.close();
}
}
接收端
package com.xie.chat;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UdpReceiveDemo1 {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(8888);
while (true){
//准备接受包裹
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);
socket.receive(packet);//阻断式接收包裹
byte[] data = packet.getData();
//这里用packet.getLength()获取真实的接收长度,如果使用data.length则是固定1024
System.out.println(data.length);
String receiveData = new String(data,0,packet.getLength());
System.out.println(receiveData);
//bye时断开连接
if (receiveData.equals("bye")){
break;
}
}
socket.close();
}
}
多线程通信
发送线程
package com.xie.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;
import java.net.SocketException;
public class TalkSend implements Runnable {
DatagramSocket socket = null;
BufferedReader reader = null;
int fromPort;
String toIp;
int toPort;
public TalkSend(int fromPort, String toIp, int toPort) {
this.fromPort = fromPort;
this.toIp = toIp;
this.toPort = toPort;
try {
socket = new DatagramSocket(fromPort);
reader = new BufferedReader(new InputStreamReader(System.in));
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
try {
String data = reader.readLine();
byte[] datas = data.getBytes();
DatagramPacket packet = new DatagramPacket(datas, 0, datas.length,
new InetSocketAddress(toIp, toPort));
socket.send(packet);
if (data.equals("bye")) {
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
socket.close();
}
}
接收线程
package com.xie.chat;
import org.omg.CORBA.PRIVATE_MEMBER;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class TalkReceive implements Runnable{
DatagramSocket socket = null;
private int port;
private String msgFrom;
public TalkReceive(int port,String msgFrom) {
this.port = port;
this.msgFrom = msgFrom;
try {
socket = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true){
try {
//准备接受包裹
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);
socket.receive(packet);//阻断式接收包裹
byte[] data = packet.getData();
//这里用packet.getLength()获取真实的接收长度,如果使用data.length则是固定1024
String receiveData = new String(data,0,packet.getLength());
System.out.println(this.msgFrom+":"+receiveData);
//bye时断开连接
if (receiveData.equals("bye")){
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
socket.close();
}
}
启动线程
package com.xie.chat;
public class TalkStudent {
public static void main(String[] args) {
//开启两个线程
new Thread(new TalkSend(6000,"localhost",9999)).start();
new Thread(new TalkReceive(8888,"老师")).start();
}
}
package com.xie.chat;
public class TalkTeacher {
public static void main(String[] args) {
//开启两个线程
new Thread(new TalkSend(6001,"localhost",8888)).start();
new Thread(new TalkReceive(9999,"学生")).start();
}
}
URL下载网络资源
package com.xie;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class lessonURL {
public static void main(String[] args) throws Exception {
//1 下载地址
URL url = new URL(
"https://m801.music.126.net/20220501154955/1a2e333692546d47b62bbccb456a75de/jdyyaac" +
"/obj/w5rDlsOJwrLDjj7CmsOj/14174788417/2483/2007/6911/8b13d701f0180708efe13fc0d97c9c9c.m4a");
//2 连接到资源
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
//3 获取输入流
InputStream inputStream = urlConnection.getInputStream();
//4 输出成文件
FileOutputStream fos = new FileOutputStream("c.m4a");
byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.read(buffer))!=-1){
fos.write(buffer,0,len);
}
fos.close();
inputStream.close();
urlConnection.disconnect();
}
}
以上仅供参考,如有疑问,留言联系
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理