前言与回顾
之前总结过网络编程的基础知识,这篇文章主要总结网络实战与应用案例
计算机网络:将地理位置不同的多台计算机通过线路连接起来,在网络系统,管理软件,以及网络协议的协调下,实现资源共享和信息传递
网络编程中通过 ip 地址和 Mac 地址定位到一台或者多台计算机,然后进行 TCP /UDP 的传输方式进行通信
IP 地址
-
唯一定位一台计算机
-
IP 分类
-
ipv4/ipv6
- ipv4: 点分十进制的格式,四个字节组成,但是在 2011 就用完了
- ipv6: 128位,8个无符号整数,由0-9,a-e 组成
2001:1111:0aaa:342b:1241:0aaa:234c:123d
-
公网(互联网)/私网(局域网)
- 192.168.xxx.xxx 专门给组织内部使用
- 具体的详细划分
-
127.0.0.1 表示本机地址
测试 IP
package Mynet;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* @Title:
* @Package
* @Description: 测试 ip
* @author: maze
* @date 2020/10/26下午 12:44
*/
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);
// 查询网址百度 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();
}
}
}
测试端口
端口号用来表示计算机上的一个进程
端口分类公有端口 0~1023
HTTP:80, HTTPS:443,FTP:21:SSH :22 Telent:23,Tomcat:8080,MySQL:3306,Oracle:1521
程序可以用的端口号:2014~49151
public class TestInetAddress {
public static void main(String[] args) {
InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1", 8080);
System.out.println(socketAddress);
System.out.println(socketAddress.getAddress());
System.out.println(socketAddress.getHostName());
}
}
TCP 聊天案例
客户端
- 连接服务器 socket
- 发送消息
服务器
- 建立服务的端口 ServerSocket
- 等待用户的连接 accept
- 接收用户消息
服务器代码
package Mynet;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @Title:
* @Package
* @Description: 服务端
* @author: maze
* @date 2020/10/26下午 14:21
*/
public class TCPServer {
public static void main(String[] args) throws IOException {
//1.定义一个服务器的套接字端口号
ServerSocket socket = new ServerSocket(9090);
//2.等待客户端连接过来
Socket accept = socket.accept();
//3.读取客户端消息
InputStream inputStream = accept.getInputStream();
//管道流
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while((len=inputStream.read(buffer))!=-1){
bos.write(buffer,0,len);
}
System.out.println(bos.toString());
//关闭流
bos.close();
inputStream.close();
accept.close();
socket.close();
}
}
客户端代码
package Mynet;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @Title:
* @Package
* @Description:客户端
* @author: maze
* @date 2020/10/26下午 14:21
*/
public class TCPClient {
public static void main(String[] args) throws IOException {
// 1.要知道服务器地址
InetAddress address = InetAddress.getByName("127.0.0.1");
int port = 9090;
//2.创建一个 socket 连接
Socket socket = new Socket(address,port);
//3.发送消息
OutputStream outputStream = socket.getOutputStream();
outputStream.write("你好,欢迎学习Java网络编程".getBytes());
//关闭流
outputStream.close();
socket.close();
}
}
文件上传案例
需求:现在我们要从客户端发送一张图片给服务器
客户端代码
package Mynet;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
/**
* @Title:
* @Package
* @Description:
* @author: maze
* @date 2020/10/26下午 15:36
*/
public class TCP2Client {
public static void main(String[] args) throws Exception {
//1.创建 socket 对象
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);
//2.创建一个输出流
OutputStream os = socket.getOutputStream();
//3.读取文件
FileInputStream fis = new FileInputStream(new File("1.jpg"));
//4.写出文件
byte[] buffer = new byte[1024];
int len = 0;
while((len = fis.read(buffer)) !=-1){
os.write(buffer,0,len);
}
// 通知服务器我结束了
socket.shutdownOutput();
// 确定服务器是否接收完毕
InputStream inputStream = socket.getInputStream();
// String byte
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer2 = new byte[1024];
int len2;
while((len2=inputStream.read(buffer2))!=-1){
baos.write(buffer2,0,len2);
}
System.out.println(baos.toString());
// 关闭流
baos.close();
inputStream.close();
fis.close();
os.close();
socket.close();
}
}
服务器代码
package Mynet;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @Title:
* @Package
* @Description:
* @author: maze
* @date 2020/10/26下午 15:36
*/
public class TCP2Server {
public static void main(String[] args) throws Exception {
// 1.创建套接字
ServerSocket serverSocket = new ServerSocket(9000);
// 2.监听客户端的连接
Socket socket = serverSocket.accept();
// 3.获取输入流
InputStream is = socket.getInputStream();
// 4.文件输出
FileOutputStream fos = new FileOutputStream(new File("2.jpg"));
byte[] buffer =new byte[1024];
int len;
while((len=is.read(buffer))!=-1){
fos.write(buffer,0,len);
}
//5.通知客户端接收完毕
OutputStream os = socket.getOutputStream();
os.write("我接收完毕了,你可以断开了".getBytes());
//关闭资源
os.close();
fos.close();
is.close();
socket.close();
serverSocket.close();
}
}
UDP 发送消息
客户端代码
package Mynet;
import java.io.IOException;
import java.net.*;
/**
* @Title:
* @Package
* @Description:
* @author: maze
* @date 2020/10/26下午 23:04
*/
public class UdpClient {
public static void main(String[] args) throws IOException {
//1.建立一个 socket
DatagramSocket socket = new DatagramSocket();
//2.建个包
String message = "服务器 你好";
// 发送的对象
InetAddress localhost = InetAddress.getByName("localhost");
int port = 9090;
// 参数: 数据,数剧的长度,要发送的对象
DatagramPacket packet = new DatagramPacket(message.getBytes(),0,message.getBytes().length,localhost,port);
//3.发送包
socket.send(packet);
//4.关闭流
socket.close();
}
}
服务器代码
package Mynet;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* @Title:
* @Package
* @Description:
* @author: maze
* @date 2020/10/26下午 23:33
*/
public class UdpServer {
public static void main(String[] args) throws IOException {
// 开放端口
DatagramSocket socket = new DatagramSocket(9090);
// 接收数据包
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();
}
}
UDP 聊天案例
客户端代码
package Mynet.chat;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
/**
* @Title:
* @Package
* @Description: 发送方
* @author: maze
* @date 2020/10/27下午 20:36
*/
public class UdpSenderDemo1 {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(8888);
// 准备数据:控制台读取
while(true) {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
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 Mynet.chat;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* @Title:
* @Package
* @Description: 接收方
* @author: maze
* @date 2020/10/27下午 20:37
*/
public class UdpSeviceDemo1 {
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 receive = new String(data,0,data.length);
System.out.println(receive);
if(receive.equals("bye")){
break;
}
}
socket.close();
}
}
UDP 多线程咨询
我们要把上面的代码修改为多线程的
封装发送消息的类
package Mynet.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;
/**
* @Title:
* @Package
* @Description: 发送消息的线程
* @author: maze
* @date 2020/10/27下午 22:09
*/
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 (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(data.equals("bye")){
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
socket.close();
}
}
封装接收消息的类
package Mynet.chat;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
/**
* @Title:
* @Package
* @Description:
* @author: maze
* @date 2020/10/27下午 22:23
*/
public class TalkRecive implements Runnable{
public static void main(String[] args) {
}
DatagramSocket socket = null;
private int port;
private String msgFrom;
public TalkRecive(int port,String msgFrom) {
this.msgFrom = msgFrom;
this.port = port;
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 receive = new String(data,0,data.length);
System.out.println(msgFrom + ":" +receive);
if(receive.equals("bye")){
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
socket.close();
}
}
学生端开启两个线程
public class TalkStudent {
public static void main(String[] args) {
new Thread(new TalkSend(7777,"localhost",9999)).start();
new Thread(new TalkRecive(8888,"老师")).start();
}
}
教师端开启两个线程
public class TalkTeacher {
public static void main(String[] args) {
new Thread(new TalkSend(5555,"localhost",8888)).start();
new Thread(new TalkRecive(9999,"学生")).start();
}
}
URL 下载网络资源
url : 统一资源定位符,定位互联网上的某个资源
package syn;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* @Title:
* @Package
* @Description: 下载网络资源
* @author: maze
* @date 2020/10/28上午 9:12
*/
public class UrlDown {
public static void main(String[] args) throws Exception {
// 1 下载这个地址的图片
URL url = new URL("https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=1538415511,2500160749&fm=26&gp=0.jpg");
//2 连接到这个资源 HTTP
HttpURLConnection urlConnection =(HttpURLConnection)url.openConnection();
//3.下载
InputStream inputStream = urlConnection.getInputStream();
FileOutputStream fos = new FileOutputStream("1.jpg");
byte[] buffer = new byte[1024];
int len;
while((len=inputStream.read(buffer))!=-1){
fos.write(buffer,0,len);
}
fos.close();
inputStream.close();
urlConnection.disconnect();
}
}