Java网络编程
IP
Java里面对应的类是InetAddress。
- 唯一定位一台网络上计算机
- 127.0.0.1:代表本机,localhost
- IP地址的分类
- IPV4/IPV6
- IPV4:4位字节
- IPV6:8个无符号整数,十六进制。
- 公网(互联网)/私网(局域网)
- ABCDE类地址
- 192.168.xxx.xxx,专门给组织内部使用
- IPV4/IPV6
//获取本机IP地址
InetAddress inetAddress1 = InetAddress.getByName("127.0.0.1");
InetAddress inetAddress2 = InetAddress.getByName("localhost");
InetAddress inetAddress3 = InetAddress.getLocalHost();
端口
端口表示计算机上的一个程序的进程。
-
不同的进程有不同的端口号!用来区分软件!
-
端口号规定为 0~65535。
-
TCP,UDP加起来就一共有 65535 * 2,不同协议同端口号不冲突,同协议同端口号冲突。
-
端口分类
-
公有端口:0~1023
- HTTP:80
- HTTPS:443
- FTP:21
- Telent:23
-
程序注册端口:1024~49151,分配用户或者程序
- Tomcat:8080
- MySql:3306
- Oracle:1521
-
动态、私有:49152~65535
netstat -ano # 查看所有的端口 netstat -ano|findstr "5900" # 查看指定端口 tasklist|findstr "8696" # 查看指定端口的进程 Ctrl + Shift + Esc # 打开任务管理器
-
通信协议
TCP
例如打电话。
- 连接、稳定。
- 三次握手、四次挥手。
- 客户端、服务端。
- 传输完成要释放连接、效率低。
UDP
例如发短信。
- 不连接、不稳定。
- 既可以是客户端也可以是服务端。
TCP连接
发送信息
客户端
- 连接服务器 Socket。
- 发送信息。
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class TcpClient {
public static void main(String[] args) {
//创建连接对象 Socket
Socket socket = null;
//创建输出流对象 OutputStream
OutputStream os = null;
try {
//1.要知道连接对象的IP地址和程序端口
//以本机作为服务器,IP地址为 127.0.0.1 ,端口统一为9999
//创建存储连接信息对象 InetAddress
InetAddress serverIP = InetAddress.getByName("127.0.0.1");
int port = 9999;
//2.Socket连接服务器,serverIP和port作为参数
socket = new Socket(serverIP, port);
//3.os发送消息IO流
os = socket.getOutputStream();
os.write("第一次实现TCP聊天".getBytes());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
服务器
- 建立服务端口 SeverSocket。
- 等待连接 accept()。
- 接受信息。
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServer {
public static void main(String[] args) {
//创建服务器对象 ServerSocket
ServerSocket serverSocket = null;
//创建连接对象 Socket
Socket socket = null;
//创建输入流对象 InputStream
InputStream is = null;
//创建管道流对象 ByteArrayOutputStream
ByteArrayOutputStream baos = null;
try {
//1.服务器的地址
//以本机作为服务器,IP地址为 127.0.0.1 ,端口统一为9999
serverSocket = new ServerSocket(9999);
while (true) {
//2.等待客户端连接 ServerSocket 的 accept() 方法
socket = serverSocket.accept();
//3.读取信息
is = socket.getInputStream();
//实例化管道流对象
baos = new ByteArrayOutputStream();
//设置每次读取最大长度
byte[] buffer = new byte[1024];
//每次读取的长度
int len;
//循环读取,若数据已读完,read返回-1,否则返回读取的数据长度int类型
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 (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
传输文件
客户端
import java.io.*;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
public class TcpClient1 {
public static void main(String[] args) throws Exception {
System.out.println("客户端启动中...");
//1.创建Socket连接对象
//================第一次握手================
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9999);
//================第三次握手================
System.out.println("客户端已连接服务器");
//2.创建输出流
OutputStream os = socket.getOutputStream();
//3.读取文件
System.out.println("客户端开始读取文件");
FileInputStream fis = new FileInputStream(new File("textOut.txt"));
System.out.println("客户端读取文件完毕");
//4.传输文件
//定义每次传输的最大长度
byte[] buffer = new byte[1024];
//定义每次传输的长度
int len;
System.out.println("客户端开始传输");
//循环读取文件流进行传输
while ((len = fis.read(buffer)) != -1) {
//传输
os.write(buffer,0,len);
}
//告诉服务器,传输完毕
//================第一次挥手================
socket.shutdownOutput();
System.out.println("客户端传输完毕");
//================第四次挥手手================
System.out.println("等待服务器确认");
//等待接收服务器通知已接收完毕,再断开连接
InputStream is = socket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//定义每次传输的最大长度
byte[] buffer2 = new byte[1024];
//定义每次传输的长度
int len2;
//循环读取文件流进行传输
while ((len2 = is.read(buffer2)) != -1) {
//传输
baos.write(buffer2,0,len2);
}
System.out.println(baos.toString());
//关闭资源
baos.close();
is.close();
fis.close();
os.close();
socket.close();
System.out.println("客户端已关闭");
}
}
服务器
import javax.naming.ldap.SortKey;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServer1 {
public static void main(String[] args) throws Exception{
System.out.println("服务器启动中...");
//1.创建服务SockerServer
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务器已启动");
//2.监听等待客户端连接
//================第二次握手================
Socket socket = serverSocket.accept();
System.out.println("客户端已连接服务器");
//3.创建输入流
InputStream is = socket.getInputStream();
//4.接收文件
FileOutputStream fos = new FileOutputStream(new File("textIn.txt"));
//定义每次传输的最大长度
byte[] buffer = new byte[1024];
//定义每次传输的长度
int len;
System.out.println("服务器开始接收");
//循环读取文件流进行传输
while ((len = is.read(buffer)) != -1) {
//传输
fos.write(buffer,0,len);
}
System.out.println("服务器接收完毕");
//================第二次挥手================
//........(可以回传数据,如果不回传则跳过,假如数据回传完毕)
//告诉客户端,接收完毕,(服务器也发完了数据,可以断开)
//================第三次挥手================
OutputStream os = socket.getOutputStream();
os.write("服务器发送:我已接收完毕(并发送完数据),可以断开了~".getBytes());
socket.shutdownOutput();
//关闭资源
os.close();
fos.close();
is.close();
socket.close();
serverSocket.close();
System.out.println("服务器已关闭");
}
}
Tomcat
服务器
- Tomcat服务器 S
客户端
- 浏览器 B
UDP连接
发送信息
发送固定的信息。
发送端
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class UDPClient1 {
public static void main(String[] args) throws Exception {
//1.建立一个地址,假设1号端口9001
DatagramSocket socket = new DatagramSocket(9001);
//2.创建数据包
//发送的内容,对方地址,端口
String msg = "这是UDP第一个客户机发送的数据!";
InetAddress inetAddress = InetAddress.getByName("localhost");
int port = 9002;
DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, inetAddress, port);
//3.发送数据
socket.send(packet);
//关闭资源
socket.close();
}
}
接收端
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPClient2 {
public static void main(String[] args) throws Exception {
//1.建立一个地址,假设1号端口9001
DatagramSocket socket = new DatagramSocket(9002);
//2.创建一个包来接收数据
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
//3.监听接收
socket.receive(packet);
//打印信息
String receiveMsg = new String(packet.getData(),0,packet.getLength());
System.out.println(receiveMsg);
//关闭资源
socket.close();
}
}
单向聊天
根据控制台输入的内容发送。
发送端
import javax.swing.plaf.TreeUI;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
public class UDPChartClient1 {
public static void main(String[] args) throws Exception {
//1.创建端口
DatagramSocket socket = new DatagramSocket(9999);
BufferedReader reader = null;
String data = null;
DatagramPacket packet = null;
while (true) {
//2.要发送的数据
//读取控制台输入流,发送内容
reader = new BufferedReader(new InputStreamReader(System.in));
data = reader.readLine();
//创建包裹
packet = new DatagramPacket(data.getBytes(), 0, data.getBytes().length, new InetSocketAddress("127.0.0.1", 8888));
//3.发送数据
socket.send(packet);
//如果发送bye,则退出聊天
if (data.equals("bye")) break;
}
//关闭数据
socket.close();
}
}
接收端
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UDPChartClient2 {
public static void main(String[] args) throws Exception {
//1.创建端口
DatagramSocket socket = new DatagramSocket(8888);
//2.准备容器
byte[] container = null;
DatagramPacket packet = null;
String receiveData = null;
while (true) {
container = new byte[1024];
packet = new DatagramPacket(container, 0, container.length);
//3.接收数据
socket.receive(packet);
//打印数据
receiveData = new String(packet.getData(), 0, packet.getLength());
System.out.println(receiveData);
//如果说bye则退出聊天
if (receiveData.equals("bye")) break;
}
//关闭数据
socket.close();
}
}
双向聊天
发送线程
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 UDPSender implements Runnable {
DatagramSocket socket = null;
BufferedReader reader = null;
private int fromPort;//起始端口
private String toIP;//目的IP地址
private int toPort;//目的端口
public UDPSender(int fromPort, String toIP, int toPort) {
this.fromPort = fromPort;
this.toIP = toIP;
this.toPort = toPort;
try {
//1.创建端口
socket = new DatagramSocket(fromPort);
//2.设置输入流
reader = new BufferedReader(new InputStreamReader(System.in));
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
String data = null;
DatagramPacket packet = null;
while (true) {
try {
//3.读取控制台输入流,发送的内容
data = reader.readLine();
//创建包裹
packet = new DatagramPacket(data.getBytes(), 0, data.getBytes().length,
new InetSocketAddress(toIP, toPort));
//4.发送数据
socket.send(packet);
//如果发送bye,则退出聊天
if (data.equals("bye")) break;
} catch (IOException e) {
e.printStackTrace();
}
}
//关闭数据
socket.close();
}
}
接收线程
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class UDPReceive implements Runnable {
DatagramSocket socket = null;
private int toPort;//目的端口,接收信息的端口
private String msgFrom;//发送者的姓名
public UDPReceive(int toPort, String msgFrom) {
this.toPort = toPort;
this.msgFrom = msgFrom;
try {
//1.创建端口
socket = new DatagramSocket(toPort);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
byte[] container = null;
DatagramPacket packet = null;
String receiveData = null;
while (true) {
try {
//2.准备容器
container = new byte[1024];
packet = new DatagramPacket(container, 0, container.length);
//3.接收数据
socket.receive(packet);
//打印数据
receiveData = new String(packet.getData(), 0, packet.getLength());
System.out.println(msgFrom + ":" + receiveData);
//如果说bye则退出聊天
if (receiveData.equals("bye")) break;
} catch (IOException e) {
e.printStackTrace();
}
}
//关闭数据
socket.close();
}
}
发送者1
public class UDPUser1 {
public static void main(String[] args) {
//发送信息的线程
new Thread(new UDPSender(7777,"127.0.0.1",9999)).start();
new Thread(new UDPReceive(8888,"user2")).start();
}
}
发送者2
public class UDPUser2 {
public static void main(String[] args) {
//发送信息的线程
new Thread(new UDPSender(5555,"127.0.0.1",8888)).start();
new Thread(new UDPReceive(9999,"user1")).start();
}
}
URL
协议://ip地址:端口号/项目名/资源
下载
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class URLDown {
public static void main(String[] args) throws IOException {
//1.下载地址
URL url = new URL("http://p1.music.126.net/LZVKKRfACTF6MvVLScaHow==/109951165614698956.jpg?imageView&quality=89");
//2.连接这个资源
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
//3.下载
//准备输入流
InputStream is = urlConnection.getInputStream();
//准备输出流,下载图片
FileOutputStream fos = new FileOutputStream("down.jpg");
//准备容器
byte[] buffer = new byte[1024];
int len;
//开始读取
while ((len = is.read(buffer)) != -1) {
//输出
fos.write(buffer,0,len);
}
//关闭资源
fos.close();
is.close();
urlConnection.disconnect();
}
}