网络编程详解
文章目录
一. 网络通信的两个要素
- 网络编程中有两个主要的问题:
如何准确的定位到网络上的一台或者多台主机
找到主机之后如何进行通信 - 网络编程中的要素:
IP和端口号 (关于ip的类)
网络通信协议 (关于TCP UDP的类 )
二. IP地址
用来唯一定位一台网络上的计算机
IP 地址的分类
-
分为IPv4和IPv6
IPv4 四字节 32位 组成 0~255
IPv6 十六字节 128位 组成 -
分为公网(互联网)和私网(局域网)
公网地址的范围:A类:地址范围1.0.0.0~127.255.255.255,主要分配给主机数量多、局域网数量少的大型网络;
B类:地址范围为128.0.0.0至191.255.255.255,一般为国际大公司及政府机构使用;
C类:地址范围为192.0.0.0至223.255.255.255,为一般小型公司校园网研究机构;
D类:地址范围由224.0.0.0至239.255.255.255。
E类:地址范围为240.0.0.0至255.255.255.255,暂时预留。
私网地址的范围:
A类地址:10.0.0.0~10.255.255.255
B类地址:172.16.0.0~172.31.255.255
C类地址:192.168.0.0~192.168.255.255
JAVA代码实现:
//测试ip
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");
InetAddress inetAddress2 = InetAddress.getByName("localhost");
InetAddress inetAddress3 = InetAddress.getLocalHost();
System.out.println(inetAddress1);
System.out.println(inetAddress2);
System.out.println(inetAddress3);
//查询网站Ip地址
InetAddress inetAddress4 = InetAddress.getByName("www.baidu.com");
System.out.println(inetAddress4);
//常用方法
System.out.println(inetAddress4.getAddress());
System.out.println(inetAddress4.getCanonicalHostName());
System.out.println(inetAddress4.getHostAddress());
System.out.println(inetAddress4.getHostName());
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
---------------结果---------------
/127.0.0.1
localhost/127.0.0.1
莫诺蒙/172.28.177.130
www.baidu.com/110.242.68.4
[B@135fbaa4
110.242.68.4
110.242.68.4
www.baidu.com
三. 端口
端口表示计算机上的一个程序的进程
不同的进程有不同的端口号!用来区分软件!
规定范围为:0~65535
常用端口号:
公有端口:0~1023
HTTP:80
HTTPS:443
FTP:21
TELNET:23
程序注册端口:1024~49151
Tomcat:8080
MySQL:3306
Oracle:1521
动态,私有:49152~65535
netstat-ano #查看所有的端口
netstat-ano | findstr “xxx” #查看指定的端口
tasklist | findstr “xxx” #查看指定端口的进程
import java.net.InetSocketAddress;
public class TestInetSocketAddress {
public static void main(String[] args) {
InetSocketAddress inetSocketAddress1 = new InetSocketAddress("127.0.0.1",8080);
InetSocketAddress inetSocketAddress2 = new InetSocketAddress("localhost",8080);
System.out.println(inetSocketAddress1);
System.out.println(inetSocketAddress2);
System.out.println(inetSocketAddress1.getAddress());
System.out.println(inetSocketAddress1.getHostName());//地址
System.out.println(inetSocketAddress1.getPort());//端口
}
}
四. 通信协议
协议:一种约定
网络通信协议:速率,传输码率,代码结构,传输控制。。。
TCP/IP协议簇
-
TCP:传输控制协议
连接,稳定
三次握手,四次挥手
客户端、服务器
传输完成,释放连接,效率低
-
UDP:用户数据报协议
不连接,不稳定
客户端,服务器没有明确的界限
不管有没有准备好,都可以发给你
DDOS攻击:洪水攻击(饱和攻击)
五. TCP
1. TCP实例
客户端:
- 连接服务端Socket
- 发送消息
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) throws UnknownHostException {
//1.要知道服务器的地址,端口号
InetAddress serverIP = InetAddress.getByName("127.0.0.1");
int port=9000;
try(//2. 创建一个socket连接
Socket socket = new Socket(serverIP,port);
OutputStream os = socket.getOutputStream();
) {
os.write("发送的消息".getBytes());
} catch (Exception e) {
e.printStackTrace();
}
}
}
服务器:
- 建立服务的端口
- 等待用户的连接accept
- 接受用户消息
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
//服务端
public class TcpSever {
public static void main(String[] args) {
while (true){
try(
//1. 我得有一个地址
ServerSocket serverSocket = new ServerSocket(9000);
//2. 等待客户端连接过来
Socket socket = serverSocket.accept();
//读取客户端的消息
InputStream is = socket.getInputStream();
//管道流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
) {
/*
老方法,在读取中文时可能会乱码
byte[] buffer = new byte[1024];
int len;
while ((len=is.read(buffer))!=-1){
String msg = new String(buffer, 0, len);
System.out.println(msg);
}
*/
byte[] buffer = new byte[1024];
int len;
while ((len=is.read(buffer))!=-1){
baos.write(buffer,0,len);
}
System.out.println(baos.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
---------------结果---------------
发送的消息
发送的消息
发送的消息
2. 文件上传
客户端
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
public class TcpClient {
public static void main(String[] args){
try(
//1. 建立socket连接
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);
//2. 创建一个输入流
OutputStream os = socket.getOutputStream();
//3. 文件流
FileInputStream fis = new FileInputStream("42.png");
//确定服务器接收完毕,才能断开连接
InputStream is = socket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream()
) {
//4. 写出文件
byte[] buffer = new byte[1024];
int len;
while ((len=fis.read(buffer))!=-1){
os.write(buffer,0,len);
}
socket.shutdownOutput();//通知服务器,我已经传输完了
//接收从服务器发来的数据并输出
byte[] buffer2 = new byte[1024];
int len2;
while ((len2=is.read(buffer2))!=-1){
baos.write(buffer2,0,len2);
}
System.out.println(baos.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}
---------------结果---------------
接收完毕
服务器
import java.io.FileOutputStream;
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) {
try(
//1. 创建一个服务
ServerSocket serverSocket = new ServerSocket(9000);
//2. 监听用户端输入
Socket socket = serverSocket.accept();//阻塞式监听,等待用户连接
//3. 获取输入流
InputStream is = socket.getInputStream();
//文件输出
FileOutputStream fos = new FileOutputStream("receive.png")) {
byte[] buffer = new byte[1024];
int len;
while ((len=is.read(buffer))!=-1){
fos.write(buffer,0,len);
}
//通知客户端接收完毕
OutputStream os = socket.getOutputStream();
os.write("接收完毕".getBytes());
} catch (Exception e){
e.printStackTrace();
}
}
}
六. Tomcat
服务器
- 自定义 S
- Tomcat服务器 S JAVA后台开发,用别人的服务器
客户端
- 自定义 C
- 浏览器 B
七. UDP
1. 消息发送实例:
发送端
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
//不需要连接服务器
public class UdpClient {
public static void main(String[] args) {
try(//1. 建立一个socket包
DatagramSocket socket = new DatagramSocket()) {
//2. 建立包
String msg="服务器你好,我是客户端";
//发送给谁
InetAddress localhost = InetAddress.getByName("localhost");
int port= 9090;
//msg.getBytes() 数据,
//0,msg.getBytes().length 数据起始
//localhost,port 发送给谁
DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, port);
socket.send(packet);
} catch (Exception e) {
e.printStackTrace();
}
}
}
接收端
import java.net.DatagramPacket;
import java.net.DatagramSocket;
//等待客户端连接
public class UdpServer {
public static void main(String[] args){
try(//开放端口
DatagramSocket socket = new DatagramSocket(9090)) {
//接受数据包
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);//接收
socket.receive(packet);//阻塞接收
System.out.println(new String(packet.getData(),0,packet.getData().length));
System.out.println(packet.getAddress().getHostAddress());
} catch (Exception e) {
e.printStackTrace();
}
}
}
---------------结果---------------
服务器你好,我是客户端
127.0.0.1
2. UDP聊天实现
实例一:
- 循环发送
//发送端
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
public class UdpSender {
public static void main(String[] args) {
try(
DatagramSocket socket = new DatagramSocket(9000);
//准备数据:控制台读取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 ("bye".equals(data)){
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
---------------发送了---------------
nihao
客户端
结束
bye
//接收端
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UdpReceive {
public static void main(String[] args) {
try(
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, packet.getLength());
System.out.println(receiveData);
if ("bye".equals(receiveData)){
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
---------------接收到---------------
nihao
客户端
结束
bye
实例二:
多线程接收发送实现
//多线程发送端
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
public class TalkSend implements Runnable{
DatagramSocket socket = null;
BufferedReader reader = null;
private int formPort;
private String toIp;
private int toPort;
public TalkSend(int formPort, String toIp, int toPort) {
this.formPort = formPort;
this.toIp = toIp;
this.toPort = toPort;
try {
socket = new DatagramSocket(formPort);
reader = new BufferedReader(new InputStreamReader(System.in));
} catch (Exception 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("bye".equals(data)){
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
socket.close();
}
}
//多线程接收端
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class TalkReceive implements Runnable{
DatagramSocket socket = null;
private int port;
public TalkReceive(int port) {
this.port = port;
try {
socket = new DatagramSocket(port);
} catch (Exception 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, packet.getLength());
System.out.println(packet.getPort()+" : "+receiveData);
if ("bye".equals(receiveData)){
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
socket.close();
}
}
//用户1
public class Talk01 {
public static void main(String[] args) {
//开启两个线程
new Thread(new TalkSend(7777,"localhost",8888)).start();
new Thread(new TalkReceive(9999)).start();
}
}
---------------结果---------------
你好
5555 : 你好
我是端口5555
5555 : 我是端口7777
再见
5555 : bye
bye
//用户2
public class Talk02 {
public static void main(String[] args) {
//开启两个线程
new Thread(new TalkSend(5555,"localhost",9999)).start();
new Thread(new TalkReceive(8888)).start();
}
}
---------------结果---------------
7777 : 你好
你好
7777 : 我是端口5555
我是端口7777
7777 : 再见
bye
7777 : bye
3. URL下载
下载URL资源
//参数
import java.net.MalformedURLException;
import java.net.URL;
public class URLDemo01 {
public static void main(String[] args) throws MalformedURLException {
URL url = new URL("http://localhost:8080/helloworld/index.jsp?username=monuomeng&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());//参数
}
}
//实现
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class URLDown {
public static void main(String[] args) throws Exception {
//下载地址
URL url = new URL("http://localhost:8080/monuomeng/SecurityFile.txt");
//连接到资源
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();//断开连接
}
}
---------------以本机tomcat文件实例---------------
下载结果如下图