网络通信三要素
- IP地址。IP地址是设备在网络中的唯一标识,IP地址包含IPv4、IPv6两种。
- 端口号。端口号是应用程序在设备中的唯一标识。
- 协议。协议是设备建立连接与数据交换格式的规则的集合。
- TCP传输控制协议:面向连接、可靠的通信,常用于文件下载、网页浏览等场景。
- UDP用户数据报协议:无连接、不可靠的通信,常用于语音通话、直播等场景。
基于TCP实现网络通信
Java提供java.net.Socket类实现客户端基于TCP协议的网络通信。
常用构造器
方法名称 | 说明 |
public Socket(String host,int post) | 通过主机名/IP地址、端口号与服务器建立连接 |
常用方法
方法名称 | 说明 |
public InputStream getInputStream( ) | 获取字节输入流(接收服务器的消息) |
public OutputStream getOutputStream( ) | 获取字节输出流(向服务器发送消息) |
public void close( ) | 释放连接资源 |
Java提供java.net.ServerSocket类实现服务器端基于TCP协议的网络通信。
常用构造器
方法名称- | 说明 |
public ServerSocket ServerSocket(int port) | 注册与客户端进行网络通信的端口号 |
常用方法
方法名称 | 说明 |
public Socket accept( ) | 阻塞等待客户端连接 |
public void close( ) | 关闭网络通信 |
1、与一个客户端通信
1.1 客户端实现网络通信
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws IOException {
//1、创建网络通信对象,建立与服务端的连接
Socket socket=new Socket("localhost",8080);
//2、获取字节输出流,并封装为数据输出流
OutputStream os = socket.getOutputStream();
DataOutputStream dos=new DataOutputStream(os);
Scanner sc=new Scanner(System.in);
while(true){
System.out.println("请出输入消息(exit表示退出):");
String msg=sc.nextLine();
if(msg.equals("exit")){
//释放资源
System.out.println("通信结束");
dos.close();
socket.close();
break;
}
//3、向服务器发送消息
dos.writeUTF(msg);
dos.flush();
}
}
}
1.2 服务器实现网络通信
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
//1、创建网络通信对象,注册与客户端连接的端口号
ServerSocket serverSocket=new ServerSocket(8080);
//2、阻塞等待客户端连接,获取socket对象
Socket socket = serverSocket.accept();
//3、获取字节输入流,并封装为数据输入流
InputStream is = socket.getInputStream();
DataInputStream dis=new DataInputStream(is);
while(true){
try{
//4、读取客户端发送的消息
String msg = dis.readUTF();
System.out.println(msg);
}catch (Exception e){ //客户端断开连接时抛出异常
//5、释放资源
dis.close();
socket.close();
break;
}
}
}
}
2、与多个客户端通信
2.1 客户端实现网络通信
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws IOException {
//1、创建网络通信对象,建立与服务端的连接
Socket socket=new Socket("localhost",8080);
//2、获取字节输出流,并封装为数据输出流
OutputStream os = socket.getOutputStream();
DataOutputStream dos=new DataOutputStream(os);
Scanner sc=new Scanner(System.in);
while(true){
System.out.println("请出输入消息(exit表示退出):");
String msg=sc.nextLine();
if(msg.equals("exit")){
//释放资源
System.out.println("通信结束");
dos.close();
socket.close();
break;
}
//3、向服务器发送消息
dos.writeUTF(msg);
dos.flush();
}
}
}
2.2 服务器实现网络通信(线程池)
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 服务器实现网络编程
*/
public class Server {
public static void main(String[] args) throws IOException {
//1、创建线程池,实现与多个客户端通信
ExecutorService pool= Executors.newFixedThreadPool(10);
//2、创建网络通信对象,注册与客户端连接的端口号
ServerSocket serverSocket=new ServerSocket(8080);
while(true){
//2、阻塞等待客户端连接,获取socket对象
Socket socket = serverSocket.accept();
//3、创建任务对象,并提交线程池处理
pool.execute(new SocketRunnable(socket));
}
}
}
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
public class SocketRunnable implements Runnable{
private Socket socket;
public SocketRunnable(Socket socket){
this.socket=socket;
}
/**
* 基于TCP协议实现网络通信
*/
public void run() {
System.out.println("用户"+socket.getRemoteSocketAddress()+"上线!");
DataInputStream dis=null;
try {
//1、获取字节输入流,并封装为数据输入流对象
InputStream is = socket.getInputStream();
dis = new DataInputStream(is);
//2、读取客户端发送的信息
while (true) {
String msg = dis.readUTF();
System.out.println(msg);
}
}catch (Exception e){
//3、释放资源
try {
dis.close();
socket.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
System.out.println("用户"+socket.getRemoteSocketAddress()+"下线!");
}
}
基于UDP实现网络通信
Java通过提供java.net.DatagramSocket类、java.net.DatagramPackage类实现UDP通信。
DatagramSocket构造器
方法名称 | 说明 |
public DatagramSocket( ) | 创建客户端Socket对象,系统随机分配端口号 |
public DatagramSocket(int port) | 创建服务端Socket对象,并指定端口号 |
DatagramSocket常用方法
方法名称 | 说明 |
public void send(DatagramPackage package) | 发送数据包 |
public void receive(DatagramPackage package) | 接收数据包 |
DatagramPackage构造器
方法名称 | 说明 |
public DatagramPackage(byte[ ] buf,int length, InetAddress host,int port) | 创建发送到指定主机助兴端口的数据包 |
1、客户端实现网络通信
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws Exception {
//1、创建网络通信对象
DatagramSocket socket=new DatagramSocket();
Scanner sc=new Scanner(System.in);
while(true){
System.out.println("请输入(exit表示结束):");
String msg= sc.nextLine();
//2、判断客户端是否结束通信
if(msg.equals("exit")){
//2.1 结束通信,释放资源
System.out.println("通信结束!");
socket.close();
break;
}
//3、创建数据包
byte[] bytes = msg.getBytes();
DatagramPacket packet=new DatagramPacket(bytes,bytes.length, InetAddress.getLocalHost(),8081);
//4、发送数据包
socket.send(packet);
}
}
}
2、服务端实现网络通信
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class Server {
public static void main(String[] args) throws Exception {
//1、创建网络通信对象
DatagramSocket socket=new DatagramSocket(8081);
//2、创建数据包用于接收客户端数据
byte[] buffer=new byte[1024*64]; //64KB
DatagramPacket packet=new DatagramPacket(buffer,buffer.length);
while(true){
//3、接收用户数据
socket.receive(packet);
//4、输出客户端消息
String msg=new String(buffer,0,packet.getLength());
System.out.println(msg);
}
}
}
注意事项:由于UDP是无连接的,因此当服务器与多客户端通信时不需要给每个客户端创建一个独立的线程。