网络编程
- 计算机网络
把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模大,功能强的网络系统,从而使众多的计算机可以方便地互相传递信息,共享硬件,软件,数据信息等资源
-
tcp/ip模型
-
ip
# 唯一的标识 internet 上的计算机 ( 通信实体 )
# 本地回环地址(hostAddress):127.0.0.1;主机名 (hostName):localhost
# IP地址分类方式一 : IPV4 IPV6
IPV4:4个字节组成,4个0~255。大概42亿个, 30亿都在北美,亚洲4亿。2011年初已经用尽。以点分十进制表示,如192.168.0.1
IPV6:128位(16个字节),写成8个无符号整数,每个整数用四个十六进制位表示,数之间用冒号 隔开,如:2001:0db8:3c4d:0015:0000:0000:1a2f:1a2b
# IP地址分类方式2:公网地址(万维网使用)和 私有地址(局域网使用)
192.168.开头的就是私有地址,范围即为 192.168.0.0 ~ 192.168.255.255,专门为组织机构内部使用
- 代码案例
import java.net.InetAddress;
import java.net.UnknownHostException;
public class InetAddressTest {
public static void main(String[] args) {
try {
InetAddress byName = InetAddress.getByName("127.0.0.1");
System.out.println(byName);
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(localHost);
InetAddress byName1 = InetAddress.getByName("www.baidu.com");
System.out.println(byName1);
// 常用方法
System.out.println(byName1.getAddress());
System.out.println(byName1.getCanonicalHostName()); // 规范的名字
System.out.println(byName1.getHostAddress()); // 获得主机地址
System.out.println(byName1.getHostName()); // 获得电脑名字
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
# 控制台
/127.0.0.1
DESKTOP-9IS6F66/192.168.1.4
www.baidu.com/180.101.49.11
[B@17c68925
180.101.49.11
180.101.49.11
www.baidu.com
- 端口号
端口表示计算机上的一个程序的进程
不同的进程有不同的端口号
被规定0-65535
公有端口0-1023
Http:80
Https:443
Ftp:21
Telnet:23
远程连接:22
程序注册端口:1024-49151,分配给用户或者程序
Tomcat:8080
MySql:3306
Oracle:1521
动态,私有:49152-65535
# 常用命令
netstat -ano # 查看所有端口
netstat -ano|findstr "端口号" # 查看指定的端口
tasklist|findstr "8696" # 查看指定端口的进程
- 代码案例
public class InetSocketAddressTest {
public static void main(String[] args) {
InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1",8080);
InetSocketAddress socketAddress2 = new InetSocketAddress("localhost",9000);
System.out.println(socketAddress.getHostName());
System.out.println(socketAddress.getAddress());
System.out.println(socketAddress.getPort());
System.out.println(socketAddress2.getHostName());
System.out.println(socketAddress2.getAddress()); //返回地址
System.out.println(socketAddress2.getPort()); //返回端口
}
}
# 控制台
127.0.0.1
127.0.0.1/127.0.0.1
8080
localhost
localhost/127.0.0.1
9000
- 网络通信协议
计算机网络中实现通信必须有一些约定,即通信协议,对速率,传输代码,代码结构,传输控制步骤,出错控制等制定标准
# 通信协议分层的思想
在制定协议时,把复杂成份分解成一些简单的成份,再将他们复合起来。最常用的复合方式是层次方式,即同层间可以通信,上一层调用下一层,而与再下一层不发生关系。各层互不影响,利于系统的开发和扩展
- TCP/IP协议簇
# 传输层协议中有两个非常重要的协议:
用户传输协议 TCP (Transmission Control Protocol)
用户数据报协议(User Datagram Protocol)
# Tcp/IP 以其两个主要协议: 传输控制协议:TCP,和网络互联协议:IP,而得名,实际上是一组协议,包括多个具有不同功能且互为关联的协议
# IP(Internet Protocol)协议是网络层的主要协议,支持网间互联的数据通信
# TCP/IP协议模型从更实用的角度出发,形成了高效的四层体系结构,即物理链路层,IP层,传输层和应用层
- TCP 和 UDP对比
# TCP协议
使用TCP协议前,必须建立TCP连接,形成传输数据通道;
传输前,采用 ‘ 三次握手 ’ 方式,点对点通信,是可靠的
TCP协议进行通信的两个应用进程:客户端,服务端
在连接中可进行大数据量的传输
传输完毕,需要释放已建立的连接,效率低
# UDP协议
将数据,源,目的封装成数据包,不需要建立连接
每个数据报的大小限制在64K内
发送方不管对方是否准备好,接收方收到也不确认,故事不可靠的
可以广播发送
发送数据结束时,无需释放资源,开销小,速度快
- tcp发送消息代码案例
# 服务器
# 建立服务的端口ServerSocket
# 等待用户的连接 accept
# 接收用户的消息
public class TcpServer {
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(); // 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) {
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();
}
}
}
}
}
# 客户端
# 连接服务器Socket
# 发送消息
public class TcpClient {
public static void main(String[] args) {
Socket socket = null;
OutputStream os = null;
try {
// 1.要知道服务器的地址,端口
InetAddress serverIp = InetAddress.getByName("127.0.0.1");
int port = 9999;
// 2.创建一个Socket连接
socket = new Socket(serverIp,port);
// 3.发送消息,相当于往外写
os = socket.getOutputStream();
String string = "我在学习网络编程...";
os.write(string.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();
}
}
}
}
}
- tcp文件上传代码案例
# 服务器
public class TcpServer {
public static void main(String[] args) throws Exception {
// 1.创建服务
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
FileOutputStream fos = null;
serverSocket = new ServerSocket(9980);
// 2.监听客户端的连接
socket = serverSocket.accept();// 阻断式连接,会一直等待客户端连接
// 3.获取输入流
is = socket.getInputStream();
// 4.文件输出
fos = new FileOutputStream(new File("picture1.jpg"));
byte[] buffer = new byte[1024];
int len;
while ((len=is.read(buffer))!=-1){
fos.write(buffer,0,len);
}
System.out.println("成功接收...");
// 5.通知客户端接收完毕
OutputStream os = socket.getOutputStream();
os.write("我接受到了,你可以关闭了...".getBytes());
// 6.关闭资源
fos.close();
os.close();
is.close();
socket.close();
serverSocket.close();
}
}
# 客户端
public class TcpClient {
public static void main(String[] args) throws Exception {
// 1.创建一个Socket连接
InetAddress serverIp = InetAddress.getByName("127.0.0.1");
int port = 9980;
Socket socket = new Socket(serverIp,port);
// 2.创建一个输出流
OutputStream os = socket.getOutputStream();
// 3.文件流 读取文件
FileInputStream fis = new FileInputStream(new File("picture.jpg"));
// 4.写出文件
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1){
os.write(buffer,0,len);
}
// 5.通知服务器,文件写出结束了
socket.shutdownOutput();
// 6.服务器确定接收后断开服务
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());
// 7.关闭资源
baos.close();
fis.close();
os.close();
is.close();
socket.close();
}
}
- udp发送消息
# 接收端
public class UdpServer {
public static void main(String[] args) throws Exception {
// 开放端口
DatagramSocket socket = new DatagramSocket(2280);
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
socket.receive(packet); // 阻塞接收
System.out.println(packet.getAddress().getHostAddress());
System.out.println(new String(packet.getData(),0,packet.getLength()));
socket.close();
}
}
# 发送端
public class UdpCliect {
public static void main(String[] args) throws Exception {
// 1.建立Socket
DatagramSocket socket = new DatagramSocket();
// 2.建包
String msg = "你好啊,服务器...";
InetAddress localhost = InetAddress.getByName("127.0.0.1");
int port = 2280;
// 数据
DatagramPacket packagt = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, port);
// 3.发送
socket.send(packagt);
// 4.关闭
socket.close();
}
}
- udp实现聊天室
# 接收端
public class UdpReceive {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(6666);
// 准备接收包裹
while (true){
byte[] container = new byte[1024];
DatagramPacket packet = new DatagramPacket(container, 0, container.length);
socket.receive(packet); // 阻塞式接收包裹
// 断开连接
byte[] data = packet.getData();
String receiveData = new String(data,0,data.length);
System.out.println(receiveData);
if (receiveData.equals("bye")){
break;
}
}
socket.close();
}
}
# 发送端
public class UdpSender {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(8888);
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("127.0.0.1",6666));
socket.send(packet);
if (data.equals("bye")){
break;
}
}
socket.close();
}
}
- udp + 多线程
# 发送端
public class TalkSend implements Runnable{
DatagramSocket socket = null;
BufferedReader reader = null;
private int fromPort;
private String toIp;
private 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(this.toIp,this.toPort));
socket.send(packet);
if (data.equals("bye")){
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
socket.close();
}
}
# 接收端
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[] container = new byte[1024];
DatagramPacket packet = new DatagramPacket(container, 0, container.length);
socket.receive(packet); // 阻塞式接收包裹
// 断开连接
byte[] data = packet.getData();
String receiveData = new String(data,0,data.length);
System.out.println(msgFrom+":"+receiveData);
if (receiveData.equals("bye")){
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
socket.close();
}
}
# 学生端
public class TalkStudent {
public static void main(String[] args) {
// 开启两个线程
new Thread(new TalkSend(7777,"127.0.0.1",9999)).start();
new Thread(new TalkReceive(8888,"老师")).start();
}
}
# 老师端
public class TalkTeacher {
public static void main(String[] args) {
// 开启两个线程
new Thread(new TalkSend(5555,"127.0.0.1",8888)).start();
new Thread(new TalkReceive(9999,"学生")).start();
}
}
- url
public class UrlTest {
// http://127.0.0.1:8080/MrXie/Security.txt
public static void main(String[] args) throws MalformedURLException {
URL url = new URL("http://127.0.0.1:8080/MrXie/Security.txt");
System.out.println(url.getProtocol()); // 协议
System.out.println(url.getHost()); // 主机
System.out.println(url.getPort()); // 端口
System.out.println(url.getPath()); // 文件
System.out.println(url.getFile()); // 文件全路径
System.out.println(url.getQuery()); // 参数
}
}
# 控制台
http
127.0.0.1
8080
/MrXie/Security.txt
/MrXie/Security.txt
null
- 使用url从网络下载资源
public class UrlDown {
public static void main(String[] args) throws IOException {
// 1.下载地址
URL url = new URL("http://127.0.0.1:8080/MrXie/Security.txt");
// 2.连接到这个资源 HTTP
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
FileOutputStream fos = new FileOutputStream("SecurityFile.txt");
byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.read(buffer))!= -1){
fos.write(buffer,0,len);
}
fos.close();
inputStream.close();
urlConnection.disconnect(); // 断开连接
}
}