网络编程
1.1 概述
1.2 网络通信的要素
如何实现网络的通信
通信双方的地址:
- ip
- 端口号
- 192.168.16,124:5900
规则:网络通信的协议
TCP/IP参考模型:
网络编程主要学传输层
小结:
- 网络编程中有两个主要的问题
- 如何准确的定位到网络上的一台或多台主机
- 找到主机之后如何进行通信
- 网络编程中的要素
- IP和端口号
- 网络通信协议
- 万物皆对象
1.3 IP
IP地址:inetAddress
- 唯一定位一台网络上计算机
- 127.0.0.1:本机localhost
- IP地址的分类
- ipv4/ipv6
- ipv4:127.0.0.1 4个字节组成 范围:0~255 一共42亿:30亿都在北美,亚洲4亿。2011年用尽
- ipv6:128位 8个无符号整数
- 公网(互联网) 私网(局域网)
- ABCD类地址
- 192.168.xx.xx 专门给组织内部使用的
- ipv4/ipv6
- 域名:记忆ip
- www.baidu.com
package study;
import java.net.InetAddress;
public class Demo2 {
public static void main(String[] args) throws Exception {
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);
// 查询网站ip地址
InetAddress inetAddress4 = InetAddress.getByName("www.baidu.com");
System.out.println(inetAddress4);
// 常用方法
System.out.println(inetAddress4.getCanonicalHostName());// 获得规范的名字
System.out.println(inetAddress4.getHostAddress());// ip
System.out.println(inetAddress4.getHostName());// 域名,或者自己电脑的名字
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
1.4 端口
端口表示计算机上的一个程序的进程
- 不同的进程有不同的端口号。用来区分软件
- 端口数规定0~65535
- TCP,UCP各有65535 单个协议下,端口号不能冲突
- 端口分类
- 公有端口0~1023
- HTTP 80
- HTTP5: 443
- FTP 21
- Telent 23
- 程序注册端口:1024~49151,分配用户或者程序
- Tomcat 8080
- MySQL 3306
- Oracle 1521
- 动态丶私有 49152~65535
- 公有端口0~1023
cmd操作
netstar -ano 查看所有端口
netstat -ano|findstr "5900" 查看指定窗口
tasklist|findstr "8696" 查看指定窗口进程
package gui;
import java.net.InetSocketAddress;
public class Demo {
public static void main(String[] args) {
InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1", 8088);
System.out.println(socketAddress);
System.out.println(socketAddress.getAddress());
System.out.println(socketAddress.getHostName());// 地址
System.out.println(socketAddress.getPort());// 端口
}
}
1.5 通信协议
网络通信协议:速率,传输码率,代码结构,传输控…
TCP/IP协议簇:实际上是一组协议
主要:
- TCP用户传输协议
- UDP 用户数据协议
出名的协议:
- TCP协议
- IP 网络互连协议
TCP:打电话
-
连接
-
三次握手,四次挥手
-
客户端丶服务端
-
传输完成,释放连接,效率低
UDP:发短信
- 不连接,不稳定
- 客户端丶服务端:没有明确的界限
- 不管有没有准备好,都可以发给你
1.6 TCP
TCP实现聊天
客户端
- 连接服务器Socket
- 发送消息
package gui;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class TCPServerDemo {
//客户端
public static void main(String[] args) {
Socket socket = null;
OutputStream os = null;
try {
// 1.要知道服务器的地址,端口号
InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
int port = 9999;
// 2.创建一个socket连接
socket = new Socket(inetAddress, port);
// 3.发送信息 IO流
os = socket.getOutputStream();
os.write("这是一段文本".getBytes());
} catch (Exception e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
}
}
服务器
- 建立服务的端口 ServerSocket
- 等待用户的链接 accept
- 接收用的消息
package gui;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpClientDemo {
//服务端
public static void main(String[] args) {
ServerSocket serv = null;
InputStream is = null;
Socket socket = null;
ByteArrayOutputStream baos = null;
try {
// 1.先设置一个地址
serv = new ServerSocket(9999);
while (true) {
//循环监听
// 2.等待客户端连接过来
socket = serv.accept();
// 3.读取客户端信息
is = socket.getInputStream();
// 为防止读入中文导致乱码,使用管道流
baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
System.out.println(baos.toString());
}
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
// 关闭资源
} finally {
if (baos != null) {
try {
baos.close();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
if (serv != null) {
try {
serv.close();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
}
}
}
文件上传
package gui;
import java.io.*;
import java.net.*;
public class TCPServerDemo {
// 服务端
public static void main(String[] args) throws Exception {
// 1.创建服务
ServerSocket serverSocket = new ServerSocket(8888);
// 2.监听客户端的连接
Socket socket = serverSocket.accept();// 阻塞式监听,会一直等待客户端连接
InputStream is = socket.getInputStream();
// 文件输出流
FileOutputStream fos = new FileOutputStream(new File("receive.png"));
byte[] buff = new byte[1024 * 3];
int len;
while ((len=is.read(buff))!=-1) {
fos.write(buff, 0, len);
}
// 通知客户端我接收完毕了
OutputStream os = socket.getOutputStream();
os.write("我接收完毕了,你可以断开了".getBytes());
fos.close();
is.close();
socket.close();
serverSocket.close();
os.close();
}
}
package gui;
import java.io.*;
import java.net.*;
public class TcpClientDemo {
// 客户端
public static void main(String[] args) throws Exception {
// 1.创建一个socket连接
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 8888);
// 2.创建一个输入流
OutputStream os = socket.getOutputStream();
// 3.读取文件
FileInputStream fis = new FileInputStream(new File("001.png"));
// 4.写出文件
byte[] buff = new byte[1024 * 3];
int len;
while ((len = fis.read(buff)) != -1) {
os.write(buff, 0, len);
}
// 通知服务器,我已经结束了
socket.shutdownOutput();
// 确认服务器接收完毕,才能断开连接
InputStream inputStream = socket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buff2 = new byte[1024];
int len2;
while ((len2 = inputStream.read(buff2)) != -1) {
baos.write(buff2, 0, len2);
}
System.out.println(baos.toString());
// 5.关闭资源
fis.close();
os.close();
socket.close();
}
}
1.7 UDP
发短信:不用连接,需要知道对方的地址
- 消息发送
发送端:
package study;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
//不需要连接服务器
public class Dome {
public static void main(String[] args) throws Exception {
// 1.建立一个socket
DatagramSocket socket = new DatagramSocket();
// 2.建包
String msg = "你好啊,服务器";
InetAddress localhost = InetAddress.getByName("localhost");
int port = 9090;
// 参数:数据,数据的长度起始,发送地址
DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, port);
// 发送包
socket.send(packet);
socket.close();
}
}
接收端:
package study;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class Demo2 {
public static void main(String[] args) throws Exception {
// 开放端口
DatagramSocket socket = new DatagramSocket(9090);
// 接收数据包
byte[] buff = new byte[1024];
DatagramPacket packet = new DatagramPacket(buff, 0, buff.length);
socket.receive(packet);
System.out.println(packet.getAddress().getHostAddress());
System.out.println(new String(packet.getData(), 0, packet.getLength()));
socket.close();
}
}
- 实现聊天
发送方
package study;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
public class Dome {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(8888);
// 准备数据:控制台读取 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", 6666));
socket.send(packet);
if (data.equals("bye")) {
break;
}
}
socket.close();
}
}
接收方
package study;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class Demo2 {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(6666);
while (true) {
// 准备接收包裹
byte[] cont = new byte[1024];
DatagramPacket packet = new DatagramPacket(cont, 0,cont.length);
socket.receive(packet);
// 断开连接
byte[] data = packet.getData();
String datas = new String(data,0,data.length);
System.out.println(datas);
if (datas.equals("bye")) {
break;
}
}
socket.close();
}
}
- 多线程在线咨询
待补充-------------------------------
1.8URL
package study;
import java.net.URL;
public class Dome {
public static void main(String[] args) throws Exception {
URL url = new URL("http://localhost:8888/helloword/index.jsp?username=lisi&password=123");
System.out.println(url.getProtocol());//协议
System.out.println(url.getHost());//主机ip
System.out.println(url.getPort());//端口
System.out.println(url.getPath());//文件
System.out.println(url.getFile());//全路径
System.out.println(url.getQuery());//参数
}
}
package study;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class Dome {
public static void main(String[] args) throws Exception {
// 1.下载地址
URL url = new URL(
"https://m10.music.126.net/20210513233041/756660deff153697dbb81bee5e628243/ymusic/075e/0f52/045c/0431c434b788a0a8a90f3658c6c0fd5f.mp3");
// 2.连接到这个资源 HTTP
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
FileOutputStream fos = new FileOutputStream("f.m4a");
byte[] buff = new byte[1024];
int len;
while ((len = inputStream.read(buff)) != -1) {
fos.write(buff, 0, len);
}
fos.close();
}
}