一、TCP和UDP协议
1、TCP协议
(1)使用TCP协议前,需先建立TCP连接,形成传输数据通道
(2)传输前,采用”三次握手”方式,是可靠的
(3)TCP协议进行通信的两个应用进程:客户端、服务端
(4)在连接中可进行大数据量的传输
(5)传输完毕,需释放已建立的连接,效率低
2、UDP协议
(1)将数据、源、目的封装成数据包,不需要建立连接
(2)每个数据报的大小限制在64KB内
(3)因无需建立连接,所以不可靠
(4)发送数据结束无需释放资源(因为不是面向连接的),速度快
(5)举例:发短信
二、ip地址和主机名的获取
//1、获取本机的InetAddress对象
InetAddress localHost = InetAddress.getLocalHost();
//获取InetAddress对象的ip地址
String hostAddress = localHost.getHostAddress();
//获取netAddress对象的主机名
String hostName = localHost.getHostName();
//2、根据指定的主机名、域名获取IP地址
InetAddress ipAdress = InetAddress.getByName("rewind.show");
三、TCP连接
0、注意
(1)写入数据必须有结束标记
(2)当客户端连接到服务端后,实际上客户端也是通过一个端口和服务端连接,不过这个端口是由TCP/IP来分配的,是随机的
1、字节流通讯
服务端
public class MyServer {
public static void main(String[] args) throws Exception {
//1、建立服务器端的Socket,配置监听端口
ServerSocket serverSocket = new ServerSocket(9000);
//2、当没有客户端连接9000端口时,程序会 阻塞,等待连接
//如果有客户端连接,则会返回Socket对象,程序继续
Socket socket = serverSocket.accept();
//3、通过输入流读取客户端写入的数据
InputStream inputStream = socket.getInputStream();
byte[] buf = new byte[1024];
int readLen = 0;
while((readLen = inputStream.read(buf)) != -1){
System.out.println(new String(buf,0,readLen));
}
//4、向客户端写入数据
OutputStream outputStream = socket.getOutputStream();
outputStream.write("来自服务端信息".getBytes());
socket.shutdownOutput();
//5、关闭流和socket
inputStream.close();
socket.close();
serverSocket.close();
}
}
客户端
public class MyClient {
public static void main(String[] args) throws IOException {
//1、连接指定主机端口
//连接成功返回socket对象,如果没有该服务端则报错
Socket socket = new Socket("127.0.0.1",9000);
//2、通过输出流写入数据
OutputStream outputStream = socket.getOutputStream();
outputStream.write("hello world!!!".getBytes());
socket.shutdownOutput(); //写入结束标记
//3、通过输入流读取服务端写入的数据
InputStream inputStream = socket.getInputStream();
byte[] buf = new byte[1024];
int readLen = 0;
while((readLen = inputStream.read(buf)) != -1){
System.out.println(new String(buf,0,readLen));
}
//4、关闭流
outputStream.close();
socket.close();
}
}
2、字符流通讯
服务端
public class MyServerWriter {
public static void main(String[] args) throws Exception {
//1、建立服务器端的Socket,配置监听端口
ServerSocket serverSocket = new ServerSocket(9000);
//2、当没有客户端连接9000端口时,程序会 阻塞,等待连接
//如果有客户端连接,则会返回Socket对象,程序继续
Socket socket = serverSocket.accept();
//3、向客户端写入数据,通过字符流
OutputStream outputStream = socket.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write("hello client!!!");
//插入一个换行符,表示写入内容结束,与socket.shutdownOutput();效果一样
// 注意:要求对方使用readLine()
bufferedWriter.newLine();
//如果使用字符流需要手动刷新,否则数据不会写入
bufferedWriter.flush();
//5、关闭流和socket
socket.close();
serverSocket.close();
bufferedWriter.close(); //关闭外层流
}
}
客户端
public class MyClientReader {
public static void main(String[] args) throws IOException {
//1、连接指定主机端口
//连接成功返回socket对象,如果没有该服务端则报错
Socket socket = new Socket("127.0.0.1",9000);
//2、通过字符流流读取服务端写入的数据
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s = bufferedReader.readLine();
System.out.println(s);
//4、关闭流
socket.close();
bufferedReader.close(); //关闭外层流
}
}
3、图片文件传输
服务端
public class MyFileDownloadServer {
public static void main(String[] args) throws Exception {
//1、建立服务器端的Socket,配置监听端口
ServerSocket serverSocket = new ServerSocket(9000);
//2、当没有客户端连接9000端口时,程序会 阻塞,等待连接
//如果有客户端连接,则会返回Socket对象,程序继续
Socket socket = serverSocket.accept();
//3、读取图片
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
byte[] bytes = StreamUtils.streamToArray(bis);
//4、存储到本地
String imgPath = "H:\\1.png";
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(imgPath));
bos.write(bytes);
bos.flush();
bis.close();
bos.close();
socket.close();
serverSocket.close();
}
}
客户端
public class MyFileUploadClient {
public static void main(String[] args) throws Exception {
//1、连接指定主机端口
//连接成功返回socket对象,如果没有该服务端则报错
Socket socket = new Socket("127.0.0.1",9000);
//2、创建读取磁盘文件的输入流
String imgPath = "H:\\图\\头像\\1.png";
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(imgPath));
//3、将输入流中的文件转化为字节数组
byte[] bytes = StreamUtils.streamToArray(bis);
//4、通过socket将文件发送给服务端
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
bos.write(bytes);
bos.flush();
//5、结束标记
socket.shutdownOutput();
bos.close();
socket.close();
}
}
工具类
public class StreamUtils {
/**
* 将输入流转化为byte[],可把文件内容读入byte[]
*/
public static byte[] streamToArray(InputStream is) throws Exception{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int len;
while((len = is.read(b)) != -1){
bos.write(b,0,len); //把读取到的数据写入输出流中
}
byte[] array = bos.toByteArray(); //将输出流中的数据转化成字节数组
bos.close();
return array;
}
}
四、UDP
基本流程
(1)核心2个类/对象,DatagramSocket
和DatagramPacket
(数据包)
(2)建立发送端、接收端(无服务端和客户端的概念)
(3)发送数据前建立数据包/报 DatagramPacket对象
(4)调用DatagramSocket
的发送和接收方法
(5)关闭DatagramSocket
注意
- 系统不保证UDP数据包一定安全到达目的地,也不保证什么时候到达。
DatagramPacket
对象封装了UDP数据包,在数据包中包含发送端和接收端的IP和端口,故不需要建立连接,最大64KB- 创建没有IP和端口号的
DatagramPacket
对象,是用来接收的UDP数据包。 - 创建含有IP和端口号的
DatagramPacket
对象,用来发送。
1、接收端
public class UDPReceiverA {
public static void main(String[] args) throws Exception {
//1、创建一个DatagramSocket对象,在指定端口接收/发送数据
DatagramSocket socket = new DatagramSocket(9000);
//2、创建一个DatagramPacket对象,用于接收数据,数据包最大64KB
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
//3、调用接收方法,将通过网络传输的 DatagramPacket 对象填充到packet对象中
//如果没有数据包发送到本机的指定端口,将会阻塞等待
socket.receive(packet);
//4、对packet进行拆包
int length = packet.getLength(); //实际接收到的数据的字节长度
byte[] data = packet.getData(); //接收到的数据
String s = new String(data, 0, length);
System.out.println(s);
socket.close();
}
}
2、发送端
public class UDPSenderB {
public static void main(String[] args) throws Exception {
//1、在9001端口接收/发送数据
DatagramSocket socket = new DatagramSocket(9001);
//2、封装发送的数据到 DatagramPacket
byte[] data = "hello world!!!".getBytes();
DatagramPacket packet = new DatagramPacket(data,data.length, InetAddress.getByName("127.0.0.1"),9000);
//3、发送数据
socket.send(packet);
socket.close();
}
}
五、win网络相关命令
查看当前主机网络情况,包括端口的监听情况和网络情况
netstat -an
//分页显示,空格翻页
netstat -an | more
//显示运行的程序,需要管理员权限
netstat -anb
//列出PID
netstat -ano
//根据端口查找PID
netstat -aon|findstr 端口号
//杀死指定PID的进程
taskkill /t /f /im PID
本地地址:本机的网络端口
外部地址:连接到指定的本地地址的的其他主机的端口
状态:LISTENING监听中,ESTABLISHED已建立连接