此博客是我看 B站 韩顺平 老师 的课程做的笔记
InetAddress类(获取IP地址)
使用代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import java.net.InetAddress; import java.net.UnknownHostException;
public class API_ { public static void main(String[] args) throws UnknownHostException { InetAddress localHost = InetAddress.getLocalHost(); System.out.println("localHost = " + localHost);
InetAddress host1 = InetAddress.getByName("Zhangyr"); System.out.println("host1 = " + host1);
InetAddress host2 = InetAddress.getByName("www.baidu.com"); System.out.println("host2 = " + host2);
String hostAddress = host1.getHostAddress(); System.out.println("host1 对应的IP = " + hostAddress); String hostName = host2.getHostName(); System.out.println("host2 对应的主机名/域名 = " + hostName); } }
|
Socket类(实现网络编程)
基本介绍
- 套接字(Sock)开发网络引用程序被广泛采用,以至于称为事实上的标准
- 通信的两端都要右Socket,是两台机器间通信的端口
- 网络通信其实就是Socket间通信
- Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输
- 一般主动发起通信的应用程序属客户端,等待通信请求的为服务端
通讯时读写数据:
socket.getOutputStream()
socket.getInputStream()
TCP编程和UDP编程
网络编程一般有TCP编程(稳定,可靠,速度慢)和UDP编程(不稳定、不可靠、速度快)两种
TCP网络通信编程
- 基于客户端——服务端的网络通信
- 底层使用的是TCP/IP协议
- 应用场景举例:客户端发送数据,服务端接收并显示
一定要关闭socket,否者后面可能会导致连接不上
TCP字节流编程
ServerSocket类:
此类实现服务器套接字。服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。
服务器套接字的实际工作由 SocketImpl 类的实例执行。应用程序可以更改创建套接字实现的套接字工厂来配置它自身,从而创建适合本地防火墙的套接字。
ServerSocket与Socket的不同,ServerSocket的每一个accept()都可连接到一个方法,可以连接很多Socket也是多并发的一个体现
Socket类:
此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器间通信的端点。
套接字的实际工作由 SocketImpl 类的实例执行。应用程序通过更改创建套接字实现的套接字工厂可以配置它自身,以创建适合本地防火墙的套接字。
编程练习1
- 编写一个服务器端和一个客户端
- 服务器端在 9999 端口监听
- 客户端连接到服务器端,发送“hello,server”,然后退出
- 服务器端接收到 客户端发送的消息,输出,并退出
代码展示
肯定要有两个程序
服务端程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket;
public class SocketTCP01Server { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(9999); System.out.println("服务端9999正在等待连接...");
Socket socket = serverSocket.accept(); System.out.println("服务端成功连接");
InputStream iis = socket.getInputStream(); int data_read = 0; byte[] buf = new byte[1024]; while((data_read = iis.read(buf)) != -1){ System.out.println(new String(buf,0,data_read)); }
iis.close(); socket.close(); System.out.println("服务端退出..."); } }
|
客户端程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import java.io.IOException; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket;
public class SocketTCP01Client { public static void main(String[] args) throws IOException { Socket socket = new Socket(InetAddress.getLocalHost(),9999); System.out.println("客户端 socket 返回 = " + socket.getClass());
OutputStream sos = socket.getOutputStream(); sos.write("Hello,server".getBytes());
sos.close(); socket.close(); System.out.println("客户端退出..."); } }
|
说明
因为是在同一台电脑上操作,所以客户端的IP地址是InetAddress.getLocalHost()也就是本地地址,如果要与别的电脑连接,就传入”xxx.xxx.xxx.xxx”
编程练习2
用字节流
- 编写一个服务端和一个客户端
- 服务端在9999端口监听
- 客户端连接到服务器端,发送”Hello,Server”,并接收服务器端回发的”Hello,Client”,再退出
- 服务器端接收到客户端发送的信息,输出,再发送”Hello,Client”,再退出
这道题的重点是发送完消息和接收完消息后都应该要有一个结束标记,即socket.shutdownOutput();socket.shutdownInput()
注意: 流要最后一起关闭,不是用完就关闭,否则会造成线程问题
代码展示
服务端代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket;
@SuppressWarnings({"all"}) public class SocketTCP02Server { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(9999); System.out.println("服务端等待连接");
Socket socket = serverSocket.accept(); System.out.println("服务端已连接");
InputStream inputStream = socket.getInputStream(); int read_length = 0; byte[] buf = new byte[1024]; while((read_length = inputStream.read(buf)) != -1){ System.out.println(new String(buf,0,read_length)); } socket.shutdownInput();
OutputStream outputStream = socket.getOutputStream(); outputStream.write("Hello,Client".getBytes()); socket.shutdownOutput();
inputStream.close(); outputStream.close(); socket.close(); System.out.println("服务端退出"); } }
|
客户端代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket;
@SuppressWarnings({"all"}) public class SocketTCP02Client { public static void main(String[] args) throws IOException { Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
OutputStream outputStream = socket.getOutputStream(); outputStream.write("Hello,Server".getBytes());
socket.shutdownOutput();
InputStream inputStream = socket.getInputStream(); int read_length = 0; byte[] buf = new byte[1024]; while((read_length = inputStream.read(buf)) != -1){ System.out.println(new String(buf,0,read_length)); } socket.shutdownInput();
outputStream.close(); inputStream.close(); socket.close(); System.out.println("客户端退出..."); } }
|
编程练习3
实际上就是第二个题,但是要求用字符流
- 编写一个服务端和一个客户端
- 服务端在9999端口监听
- 客户端连接到服务端,发送”Hello,Server”,并接收服务端回发的”Hello,Client”,再退出
- 服务端接收接收到客户端发送的信息,输出,再发送”Hello,Client”,再退出
需要使用转换流,即OutputStream->Writer;InputStream->Reader。并且,可以使用Writer.newLine()来作为结束标记,但是,需要使用readLine()来读取[这就相当于是一种协议了]
代码展示
服务端代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| import java.io.*; import java.net.ServerSocket; import java.net.Socket;
@SuppressWarnings({"all"}) public class SocketTCP03Server { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(9999); Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String s = bufferedReader.readLine(); System.out.println(s);
OutputStream outputStream = socket.getOutputStream(); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream); BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter); bufferedWriter.write("Hello,Client"); bufferedWriter.newLine(); bufferedWriter.flush();
bufferedWriter.close(); bufferedReader.close(); socket.close(); } }
|
客户端代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| import java.io.*; import java.net.InetAddress; import java.net.Socket;
@SuppressWarnings({"all"}) public class SocketTCP03Client { public static void main(String[] args) throws IOException { Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
OutputStream outputStream = socket.getOutputStream(); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream); BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter); bufferedWriter.write("Hello,Server"); bufferedWriter.newLine(); bufferedWriter.flush();
InputStream inputStream = socket.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String s = bufferedReader.readLine(); System.out.println(s);
bufferedWriter.close(); bufferedReader.close(); socket.close(); } }
|
TCP文件编程
编程练习1
- 编写一个服务端和一个客户端
- 服务端在9999端口监听
- 客户端连接到服务端,发送一张图片,之后退出
- 服务器端接收到客户端发送的图片,保存到e盘下
- 该程序需要使用
StreamUtils.java;
、 BufferedInputStream
和BufferedOutputStream
代码展示
服务端代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import java.io.*; import java.net.ServerSocket; import java.net.Socket;
public class TCPFileUploadServer { public static void main(String[] args) throws Exception { ServerSocket serverSocket = new ServerSocket(9999); System.out.println("服务端在9999端口监听..."); Socket socket = serverSocket.accept(); System.out.println("等待连接...");
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream()); byte[] bytes = StreamUtils.streamToByteArray(bis); String filePath = "src\\鹅国小酒馆3.mp4"; BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath)); bos.write(bytes);
bos.close(); bis.close(); socket.close(); serverSocket.close(); } }
|
客户端代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import java.io.*; import java.net.InetAddress; import java.net.Socket;
public class TCPFileUploadClient { public static void main(String[] args) throws Exception { Socket socket = new Socket(InetAddress.getLocalHost(), 9999); String filePath = "e:\\鹅国小酒馆.mp4"; BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath)); byte[] bytes = StreamUtils.streamToByteArray(bis); BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream()); bos.write(bytes); bis.close(); socket.shutdownOutput();
bos.close(); socket.close(); } }
|
编程练习2
是编程练习1的进阶
- 编写一个服务端和一个客户端
- 服务端在9999端口监听
- 客户端连接到服务端,发送一张图片
- 服务器端接收到客户端发送的图片,保存到e盘,发送”收到图片”再退出
- 客户端接收到服务器端发送的”收到图片”后再退出
- 该程序需要使用
StreamUtils.java;
、 BufferedInputStream
和BufferedOutputStream
代码展示
服务端代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| import java.io.*; import java.net.ServerSocket; import java.net.Socket;
public class TCPFileUploadServer { public static void main(String[] args) throws Exception { ServerSocket serverSocket = new ServerSocket(9999); System.out.println("服务端在9999端口监听..."); Socket socket = serverSocket.accept(); System.out.println("等待连接...");
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream()); byte[] bytes = StreamUtils.streamToByteArray(bis); String filePath = "e:\\鹅国小酒馆3.mp4"; BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath)); bos.write(bytes); bos.close();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); bw.write("收到图片"); bw.flush(); socket.shutdownOutput();
bw.close(); bis.close(); socket.close(); serverSocket.close(); } }
|
客户端代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| import java.io.*; import java.net.InetAddress; import java.net.Socket;
public class TCPFileUploadClient { public static void main(String[] args) throws Exception { Socket socket = new Socket(InetAddress.getLocalHost(), 9999); String filePath = "e:\\鹅国小酒馆.mp4"; BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath)); byte[] bytes = StreamUtils.streamToByteArray(bis); BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream()); bos.write(bytes); bis.close(); socket.shutdownOutput();
InputStream inputStream = socket.getInputStream(); String s = StreamUtils.streamToString(inputStream); System.out.println(s);
inputStream.close(); bos.close(); socket.close(); } }
|
netstat指令
- netstat -an可以查看当前主机网络情况,包括端口监听情况和网络连接情况
- netstat -an|more 可以分页显示
- netstat -anb|more 可以分页显示并且可以显示使用的程序
- 要求在dos控制台下执行
其中本地地址冒号后面的数字代表端口(一般都是服务端),外部地址一般是客户端的IP地址(127.0.0.1还是表示本地地址),状态表示是否是在监听
运行服务端程序。
TCP连接秘密
当连接上后,客户端也会有一个端口(这个端口是随机的),假设使用客户端与服务端连接后,上图中能找到一个外部地址与本地地址为0.0.0.0:9999连接的地址,后面的冒号代表地址,并且状态为ESTABLISHED
UDP网络编程
基本介绍
- 类
DatagramSocket
和 DatagramPacket
[数据包/数据报] 实现了基于UDP协议网络程序
- UDP数据报通过数据报套接字 DatagramSocket发送和接收,系统不保证UDP数据报一定能够安全送到目的地,也不能确定什么时候可以送达
- DatagramPacket对象封装了UDP数据报,在数据报中包含了发送端口的IP地址和的端口号以及接收端口的IP地址和端口号
- UDP协议中每个数据报都给出了完整的地址信息,因此无需建立发送方和接收方的连接
编程练习
- 编写一个接收端A,和一个发送端B
- 接收端A在9999端口等待接收数据
- 发送端B向接收端A发送数据,发送”Hello,明天吃火锅”
- 接收端A接收到发送端B的数据后,回复”好的,明天见”,退出
- 发送端B接收到数据后再退出