网络编程(Socket编程)
IP和PORT
IP的简介和分类
简介
IP(Internet Protocol)网络互联协议(互联网协议),是TCP/IP协议组的核心协议之一。IP和子网掩码构成了一台计算机在一个网络中的唯一识别。IP有IPv4和IPv6之分,这里重点说IPv4,IPv4的IP通常由4个十进制数字表示:xxx.xxx.xxx.xxx xxx在底层用二进制表示是一个字节(Byte),一个字节是8bit位 ,xxx用二进制表示取值范围就是0000 0000 --1111 11111 ,就是2的8次256个数字,因为从0开始,最大到255。
分类

端口(port)的简介和分类
简介
PORT(端口)是计算机的逻辑概念。上面使用IP能找到一台电脑,端口(Port)就是这台电脑上的网络服务或者网络应用的唯一识别。
端口在底层通常使用2个字节(1Byte=8bit)来表示,最大的表示的端口数就是2的16次方65536。但是端口是从0开始,最大的端口就是65535。
例如:tomcat 8080 ftp 21 ssh 22 http 80 https 443 mysql 3306
分类

TCP和UDP

TCP概念和特点
TCP(Transmission Control Protocol) 传输控制协议。面相链接编程,占用资源高,数据可靠性好,底层使用IO流进行数据传输,支持一对一,不支持广播(一对多)。
UDP概念和特点
UDP(User Datagram Protocol)用户数据报协议。面相无连接编程,占用资源低,数据可靠性差,底层使用数据报进行数据传输,支持一对一,也支持广播(一对多)。
java TCP编程
工作流程
服务端
1,使用端口号,实例化ServerSocket,为数据传输做准备
2,调用ServerSocker中的accept方法,等待客户端传入数据(没有传入数据之前一直等待)
3,使用InputStream接口接收客户端输入数据
4,使用OutStream接口向客户端输出数据
5,关闭资源
客户端
1,使用IP和PORT端口创建Socket对象,为数据传输做准备
2,使用OutputStream接口向服务端输出数据
3,使用InputStream接口接受服务端输入的数据
4,关闭资源
简单数据传输示例
服务端
package com.aaa.tcp.demo1;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @FileName: Server
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/22 10:55
* @Version: 1.0.0
*/
public class Server {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream inputStream = null;
OutputStream outputStream = null;
BufferedReader bufferedReader = null;
PrintWriter printWriter = null;
try {
//1,使用端口号,实例化ServerSocket,为数据传输做准备
//ServerSocket 这个类实现了服务器套接字。 服务器套接字等待通过网络进入的请求。
// 它根据该请求执行一些操作,然后可能将结果返回给请求者。
//Socket 该类实现客户端套接字(也称为“套接字”)。 套接字是两台机器之间通讯的端点。
serverSocket = new ServerSocket(18888);//端口 1024-49151
//打印提示
System.out.println("服务器已经准备就绪,等待客户端传入数据!!!!");
//2,调用ServerSocker中的accept方法,等待客户端传入数据(没有传入数据之前一直等待)
//accept() 侦听要连接到此套接字并接受它。 该方法将阻塞直到建立连接。
socket = serverSocket.accept();
//3,使用InputStream接口接收客户端输入数据
inputStream = socket.getInputStream();
//可能要传输中文,最好使用字符流进行接受,避免中文乱码 把字节流转成字符流
//为了提高字符流的读写效率,可以在流上套接缓冲流,提高读写速度
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
//bufferedReader支持按行读取
String clietMsg = bufferedReader.readLine();
//打印信息
System.out.println("客户端说:"+clietMsg);
//4,使用OutStream接口向客户端输出数据
outputStream = socket.getOutputStream();
//直接使用outputStream 响应客户端,如果传递中文可能会乱码,不能按行响应,套接上 printWriter 可以直接按行响应
printWriter = new PrintWriter(outputStream);
//向客户端打印
printWriter.println("客户端:你好,你发送的"+clietMsg+"信息,我已经收到!");
//刷新管道
printWriter.flush();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
//5,关闭资源 关闭流的原则:先打开的后关闭,有套接关系的,先关闭被套接的流
if(outputStream!=null){
outputStream.close();
}
if(inputStream!=null){
inputStream.close();
}
if(bufferedReader!=null){
bufferedReader.close();
}
if(socket!=null){
socket.close();
}
if(serverSocket!=null){
serverSocket.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
客户端
package com.aaa.tcp.demo1;
import java.io.*;
import java.net.Socket;
/**
* @FileName: Client
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/22 14:06
* @Version: 1.0.0
*/
public class Client {
public static void main(String[] args) {
Socket socket = null;
OutputStream outputStream = null;
PrintWriter printWriter = null;
InputStream inputStream = null;
BufferedReader bufferedReader = null;
try {
//1,使用IP和PORT端口创建Socket对象,为数据传输做准备
//创建流套接字并将其连接到指定主机上的指定端口号。
// Socket socket = new Socket("localhost",18888);
// Socket socket = new Socket("127.0.0.1",18888);
socket = new Socket("172.16.2.75",18888);
//2,使用OutputStream接口向服务端输出数据
outputStream = socket.getOutputStream();
printWriter = new PrintWriter(outputStream);
printWriter.println("你好!");
//刷新管道
printWriter.flush();
//3,使用InputStream接口接受服务端输入的数据
inputStream = socket.getInputStream();
//转字符流,套接缓冲流
bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"utf-8"));
//读取并打印
String sererMsg = bufferedReader.readLine();
System.out.println("服务器说:"+sererMsg);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
//4,关闭资源
try {
if(inputStream!=null){
inputStream.close();
}
if(bufferedReader!=null){
bufferedReader.close();
}
if(outputStream!=null){
outputStream.close();
}
if(printWriter!=null){
printWriter.close();
}
if(socket!=null){
socket.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
控制台对聊
服务器
package com.aaa.tcp.demo2;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
/**
* @FileName: Server
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/22 10:55
* @Version: 1.0.0
*/
public class Server {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream inputStream = null;
OutputStream outputStream = null;
BufferedReader bufferedReader = null;
PrintWriter printWriter = null;
try {
//1,使用端口号,实例化ServerSocket,为数据传输做准备
//ServerSocket 这个类实现了服务器套接字。 服务器套接字等待通过网络进入的请求。
// 它根据该请求执行一些操作,然后可能将结果返回给请求者。
//Socket 该类实现客户端套接字(也称为“套接字”)。 套接字是两台机器之间通讯的端点。
serverSocket = new ServerSocket(19999);//端口 1024-49151
//打印提示
System.out.println("服务器已经准备就绪,等待客户端传入数据!!!!");
//2,调用ServerSocker中的accept方法,等待客户端传入数据(没有传入数据之前一直等待)
//accept() 侦听要连接到此套接字并接受它。 该方法将阻塞直到建立连接。
socket = serverSocket.accept();
//3,使用InputStream接口接收客户端输入数据
inputStream = socket.getInputStream();
//可能要传输中文,最好使用字符流进行接受,避免中文乱码 把字节流转成字符流
//为了提高字符流的读写效率,可以在流上套接缓冲流,提高读写速度
// 支持中文:GBK = big5 大五码(繁体字,中国香港,台湾使用比较多) +gb2312(简体字) gb2312(guo biao) gbk(guo biao kuo)
// 不支持中文: ISO-8859-1
// Unicode编码:万国码,国际码 utf-8 unicode拓展码 支持全世界各国的语言的
bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"utf-8"));
//4,使用OutStream接口向客户端输出数据
outputStream = socket.getOutputStream();
//直接使用outputStream 响应客户端,如果传递中文可能会乱码,不能按行响应,套接上 printWriter 可以直接按行响应
printWriter = new PrintWriter(outputStream);
//实例化扫描器类
Scanner scanner = new Scanner(System.in);
//使用死循环一直读取客户端信息
while (true) {
//bufferedReader支持按行读取
String clietMsg = bufferedReader.readLine();
//打印信息
System.out.println("客户端说:" + clietMsg);
//判断客户端的信息,如果含有借钱 就退出
if(clietMsg.contains("借钱")){
//向客户端打印
printWriter.println("你被拉黑了");
//刷新管道
printWriter.flush();
break;
}
//打印提示
System.out.println("请输入:");
//收集控制台信息,输入之前一直阻塞
String inputMsg = scanner.next();
//向客户端打印
printWriter.println(inputMsg);
//刷新管道
printWriter.flush();
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
//5,关闭资源 关闭流的原则:先打开的后关闭,有套接关系的,先关闭被套接的流
if(outputStream!=null){
outputStream.close();
}
if(inputStream!=null){
inputStream.close();
}
if(bufferedReader!=null){
bufferedReader.close();
}
if(socket!=null){
socket.close();
}
if(serverSocket!=null){
serverSocket.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
客户端
package com.aaa.tcp.demo2;
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
/**
* @FileName: Client
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/22 14:06
* @Version: 1.0.0
*/
public class Client {
public static void main(String[] args) {
Socket socket = null;
OutputStream outputStream = null;
PrintWriter printWriter = null;
InputStream inputStream = null;
BufferedReader bufferedReader = null;
try {
//1,使用IP和PORT端口创建Socket对象,为数据传输做准备
//创建流套接字并将其连接到指定主机上的指定端口号。
// Socket socket = new Socket("localhost",18888);
// Socket socket = new Socket("127.0.0.1",18888);
socket = new Socket("172.16.2.75",19999);
//2,使用OutputStream接口向服务端输出数据
outputStream = socket.getOutputStream();
printWriter = new PrintWriter(outputStream);
//3,使用InputStream接口接受服务端输入的数据
inputStream = socket.getInputStream();
//转字符流,套接缓冲流
bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"utf-8"));
//实例化扫描器类
Scanner scanner = new Scanner(System.in);
//使用死循环一直读取客户端信息
while (true) {
//打印提示
System.out.println("请输入:");
//收集控制台信息,输入之前一直阻塞
String inputMsg = scanner.next();
printWriter.println(inputMsg);
//刷新管道
printWriter.flush();
//读取并打印
String sererMsg = bufferedReader.readLine();
System.out.println("服务器说:"+sererMsg);
//判断客户端的信息,如果含有借钱 就退出
if(sererMsg.contains("拉黑")){
//向客户端打印
printWriter.println("借钱");
//刷新管道
printWriter.flush();
break;
}
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
//4,关闭资源
try {
if(inputStream!=null){
inputStream.close();
}
if(bufferedReader!=null){
bufferedReader.close();
}
if(outputStream!=null){
outputStream.close();
}
if(printWriter!=null){
printWriter.close();
}
if(socket!=null){
socket.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
java UDP编程
工作流程

简单例子
服务端
package com.aaa.udp.demo1;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
/**
* @FileName: Server
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/22 16:25
* @Version: 1.0.0
*/
public class Server {
public static void main(String[] args) {
DatagramSocket datagramSocket = null;
try {
//1,实例化数据的发送或者接收对象DatagramSocket
//DatagramSocket 此类表示用于发送和接收数据报数据包的套接字。
datagramSocket = new DatagramSocket();
//2,准备发送数据
String sendMessage = "hello qy178!!!你好,中国!!!";
//转换为数组
byte[] sendMessageByteArray = sendMessage.getBytes("utf-8");
//3,封装数据报包对象DatagramPacket
//DatagramPacket 该类表示数据报包。
//getByName 返回值就是InetAddress的对象
DatagramPacket datagramPacket =new DatagramPacket(sendMessageByteArray,sendMessageByteArray.length
, InetAddress.getByName("172.16.2.75"),16868);
//4,发送数据
datagramSocket.send(datagramPacket);
//打印提示
System.out.println("数据发送完成!");
} catch (SocketException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
//5,关闭资源
if(datagramSocket!=null) {
datagramSocket.close();
}
}
}
}
客户端
package com.aaa.udp.demo1;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
/**
* @FileName: Client
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/22 16:25
* @Version: 1.0.0
*/
public class Client {
public static void main(String[] args) {
DatagramSocket datagramSocket = null;
try {
//1,实例化数据的发送或者接收对象DatagramSocket
datagramSocket = new DatagramSocket(16868);
// hello qy178!!!你好,中国!!!
//2,准备字节缓冲数组 [h,e,l,l,o, ,q, ....,!] A=67 a=96
byte[] receiveMsgByteArray = new byte[2048];
//3,封装接受数据对象DatagramPackage,接受数据
DatagramPacket datagramPacket =new DatagramPacket(receiveMsgByteArray,2048);
//打印提示
System.out.println("客户端等待接受数据!!!!!!!!");
// receive 从此套接字接收数据报包。 当此方法返回时, DatagramPacket的缓冲区将填充接收到的数据。
//该方法阻塞,直到接收到数据报。
datagramSocket.receive(datagramPacket);
//4,组装数组并打印
//datagramPacket.getLength() 返回要发送的数据的长度或接收到的数据的长度。
String receiveMsg = new String(receiveMsgByteArray, 0, datagramPacket.getLength(), "utf-8");
System.out.println("接受到的数据为:"+receiveMsg);
} catch (SocketException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
//5,关闭资源
if(datagramSocket!=null){
datagramSocket.close();
}
}
}
}
广播例子
需求
编写发送震动飞秋的代码,让局域网内的所有飞秋同时震动!
package com.aaa.udp.demo2;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
/**
* @FileName: Server
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/22 17:10
* @Version: 1.0.0
*/
public class Server {
public static void main(String[] args) {
DatagramSocket datagramSocket = null;
try {
//1,实例化数据的发送或者接收对象DatagramSocket
//DatagramSocket 此类表示用于发送和接收数据报数据包的套接字。
datagramSocket = new DatagramSocket();
//2,准备发送数据
String sendMessage = "1_lbt4_0#128#000C29D68D8F#0#0#0#2.5a:1399716676:%s:%s:209:.";
//转换为数组
byte[] sendMessageByteArray = sendMessage.getBytes("utf-8");
while (true) {
for (int i = 3; i <= 254; i++) {
//3,封装数据报包对象DatagramPacket
//DatagramPacket 该类表示数据报包。
//getByName 返回值就是InetAddress的对象
DatagramPacket datagramPacket = new DatagramPacket(sendMessageByteArray, sendMessageByteArray.length
, InetAddress.getByName("172.16.2." + i), 2425);
//4,发送数据
datagramSocket.send(datagramPacket);
}
Thread.sleep(3000);
//打印提示
System.out.println("数据发送完成!");
}
} catch (SocketException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
//5,关闭资源
if(datagramSocket!=null) {
datagramSocket.close();
}
}
}
}
浙公网安备 33010602011771号