什么是网络通信:可以让设备中的程序与网络上其他设备中的程序进行数据交互
基本的通信架构:CS架构(Client客户端/Server服务端)、BS架构(Browser浏览器/Server服务端)
一、网络通信三要素
1.IP地址
//1.获取本机IP地址对象
InetAddress ip1 = InetAddress.getLocalHost();
System.out.println(ip1.getHostName());
System.out.println(ip1.getHostAddress());
//2.获取指定IP或者指定域名的IP地址对象
InetAddress ip2 = InetAddress.getByName("www.baidu.com");
System.out.println(ip2.getHostName());
System.out.println(ip2.getHostAddress());
//3.在指定毫秒内,判断主机与该ip对应的主机是否能连通
System.out.println(ip2.isReachable(6000));
2.端口号
3.协议
二、UDP通信
1.一发一收
public class Server {
public static void main(String[] args) throws Exception {
System.out.println("服务端启动");
//1.创建一个服务端对象(注册端口)
DatagramSocket socket = new DatagramSocket(6666);
//2.创建一个数据包对象,用于接收数据
byte[] buffer = new byte[1024 * 64];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
//3.使用数据包接收客户端发来的数据
socket.receive(packet);
//4.从字节数组中把接收到的数据打印出来
int len = packet.getLength();//获取本次数据包接收了多少数据
String s = new String(buffer,0,len);
System.out.println(s);
socket.close();
}
}
public class Client {
public static void main(String[] args) throws Exception {
/*
实现UDP通信一发一收
*/
//1.创建客户端对象
DatagramSocket socket = new DatagramSocket();
//2.创建数据包对象封装要发出去的数据
/*
byte buf[], int length, InetAddress address, int port
封装要发出去的数据 发送出去的数据字节个数 服务端的IP地址 服务端程序的端口
*/
byte[] bytes = "我是快乐的客户端,我爱你abc".getBytes();
DatagramPacket packet = new DatagramPacket(bytes, bytes.length,
InetAddress.getLocalHost(),6666);
//3.发送数据包
socket.send(packet);
System.out.println("客户端数据发送完毕");
socket.close();
}
}
2.多发多收
public class Server {
public static void main(String[] args) throws Exception {
System.out.println("服务端启动");
//1.创建一个服务端对象(注册端口)
DatagramSocket socket = new DatagramSocket(6666);
//2.创建一个数据包对象,用于接收数据
byte[] buffer = new byte[1024 * 64];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
while (true) {
//3.使用数据包接收客户端发来的数据
socket.receive(packet);
//4.从字节数组中把接收到的数据打印出来
int len = packet.getLength();//获取本次数据包接收了多少数据
String s = new String(buffer,0,len);
System.out.println(s);
System.out.println("----------");
}
}
}
public class Client {
public static void main(String[] args) throws Exception {
/*
实现UDP通信多发多收
*/
//1.创建客户端对象
DatagramSocket socket = new DatagramSocket();
//2.创建数据包对象封装要发出去的数据
/*
byte buf[], int length, InetAddress address, int port
封装要发出去的数据 发送出去的数据字节个数 服务端的IP地址 服务端程序的端口
*/
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请说");
String msg = sc.nextLine();
//一旦发现用户输入的是exit命令,就退出客户端
if ("exit".equals(msg)){
System.out.println("欢迎下次光临!退出成功");
socket.close();//释放资源
break;
}
byte[] bytes = msg.getBytes();
DatagramPacket packet = new DatagramPacket(bytes, bytes.length,
InetAddress.getLocalHost(),6666);
//3.发送数据包
socket.send(packet);
}
}
}
三、TCP通信
1.一发一收
public class Client {
public static void main(String[] args) throws Exception {
/*
实现TCP通信一发一收
*/
//1.创建Socket对象,并同时请求与服务端程序的链接
Socket socket = new Socket("192.168.1.103", 8888);
//2.从Socket通信管道中得到一个字节输出流,用来发数据给服务器程序
OutputStream os = socket.getOutputStream();
//3.把低级的字节输出流包装成数据输出流
DataOutputStream dos = new DataOutputStream(os);
//4.写数据出去
dos.writeUTF("在一起好吗");
dos.close();
socket.close();
}
}
public class Server {
public static void main(String[] args) throws Exception {
System.out.println("---服务端启动成功---");
//1.创建ServerSocket对象,同时为服务器注册端口号
ServerSocket serverSocket = new ServerSocket(8888);
//2.使用ServerSocket对象,调用accept方法,等待客户端连接请求
Socket accept = serverSocket.accept();
//3.从socket管道中得到字节输入流
InputStream is = accept.getInputStream();
//4.把原始的字节输入流包装成数据输入流
DataInputStream dis = new DataInputStream(is);
//5.使用数据输入流读取客户端发送的消息
String rs = dis.readUTF();
System.out.println(rs);
//也可以获取客户端的IP地址
System.out.println(accept.getRemoteSocketAddress());
dis.close();
accept.close();
}
}
2.多发多收
public class Server {
public static void main(String[] args) throws Exception {
System.out.println("---服务端启动成功---");
//1.创建ServerSocket对象,同时为服务器注册端口号
ServerSocket serverSocket = new ServerSocket(8888);
//2.使用ServerSocket对象,调用accept方法,等待客户端连接请求
Socket socket = serverSocket.accept();
//3.从socket管道中得到字节输入流
InputStream is = socket.getInputStream();
//4.把原始的字节输入流包装成数据输入流
DataInputStream dis = new DataInputStream(is);
while (true) {
try {
//5.使用数据输入流读取客户端发送的消息
String rs = dis.readUTF();
System.out.println(rs);
} catch (Exception e) {
System.out.println(socket.getRemoteSocketAddress() + "离线了");
dis.close();
socket.close();
break;
}
}
}
}
public class Client {
public static void main(String[] args) throws Exception {
/*
实现TCP通信多发多收
*/
//1.创建Socket对象,并同时请求与服务端程序的链接
Socket socket = new Socket("192.168.1.103", 8888);
//2.从Socket通信管道中得到一个字节输出流,用来发数据给服务器程序
OutputStream os = socket.getOutputStream();
//3.把低级的字节输出流包装成数据输出流
DataOutputStream dos = new DataOutputStream(os);
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请说");
String s = sc.nextLine();
//一旦用户输入了exit,就退出客户端程序
if ("exit".equals(s)){
System.out.println("退出成功");
dos.close();
socket.close();
break;
}
//4.写数据出去
dos.writeUTF(s);
dos.flush();
}
}
}
3.与多个客户端同时通信
public class Server {
public static void main(String[] args) throws Exception {
System.out.println("---服务端启动成功---");
//1.创建ServerSocket对象,同时为服务器注册端口号
ServerSocket serverSocket = new ServerSocket(8888);
while (true) {
//2.使用ServerSocket对象,调用accept方法,等待客户端连接请求
Socket socket = serverSocket.accept();
System.out.println("有人上线了" + socket.getRemoteSocketAddress());
//3.把这个客户端对应的socket通信管道,交给一个独立的线程负责处理
new ServerReaderThread(socket).start();
}
}
}
public class ServerReaderThread extends Thread{
private Socket socket;
public ServerReaderThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
try {
InputStream is = socket.getInputStream();
DataInputStream dis = new DataInputStream(is);
while (true){
try {
String msg = dis.readUTF();
System.out.println(msg);
} catch (Exception e) {
System.out.println("有人下线了:" + socket.getRemoteSocketAddress());
dis.close();
socket.close();
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class Client {
public static void main(String[] args) throws Exception {
//1.创建Socket对象,并同时请求与服务端程序的链接
Socket socket = new Socket("192.168.1.103", 8888);
//2.从Socket通信管道中得到一个字节输出流,用来发数据给服务器程序
OutputStream os = socket.getOutputStream();
//3.把低级的字节输出流包装成数据输出流
DataOutputStream dos = new DataOutputStream(os);
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请说");
String s = sc.nextLine();
//一旦用户输入了exit,就退出客户端程序
if ("exit".equals(s)){
System.out.println("退出成功");
dos.close();
socket.close();
break;
}
//4.写数据出去
dos.writeUTF(s);
dos.flush();
}
}
}