网络通讯
网络通信简介
网络通信协议主要包含两个方面的定义:
-
定义了进程之间交换消息所必需遵循的顺序。
-
定义进程之间所交换的消息的格式。
两个进程只要遵循相同的协议,就可以相互交换信息,而这两个进程可以用不同的编程语言编写,可以位于两个完全不同的计算机上。
URL通信
-
统一资源定位符:<传输协议>://<主机名>:<端口号>/<文件名>#<引用>引用>文件名>端口号>主机名>传输协议>
-
URL类
import java.io.*; import java.net.*; public class URL1{ public static void main(String[] args) throws IOException { URL url = new URL("http://www.javajeff.com/articles/articles/html"); System.out.println("Authority = " + url.getAuthority()); System.out.println("Default port = " + url.getDefaultPort()); System.out.println("File = " + url.getFile()); System.out.println("Host = " + url.getHost()); System.out.println("Path = " + url.getPath()); System.out.println("Port = " + url.getPort()); System.out.println("Protocol = " + url.getProtocol()); System.out.println("Query = " + url.getQuery()); System.out.println("Ref = " + url.getRef()); System.out.println("User Info = " + url.getUserInfo()); }
-
字节流访问www资源:通过URL对象访问指定的www资源,调用URL的openStream方法
import java.io.*; import java.net.*; public class URL2{ // 对于不想处理的Exception直接throws,不用catch public static void main (String [] args) throws IOException{ // 需要说明协议 URL url = new URL (“http://www.javajeff.com/articles/articles/html”); InputStreamReader isr = new InputStreamReader (url.openStream (),"UTF-8"); BufferedReader br=new BufferedReader(isr); String s; while ((s = br.readLine ()) != null) System.out.print(s); br.close(); } }
-
URLConnection实现双向通信:
import java.io.*; import java.net.*; public class ComWithCgi{ public static void main(String[] args) throws Exception { // 建立指向本地磁盘上cgi的URL对象 URL url = new URL(“http:/java.sun.com/test.cgi”); URLConnection connection = url.openConnection(); connection.setDoOutput(true); PrintStream ps = new PrintStream(connection.getOutputStream()); ps.println("0123456789"); ps.close(); // 向服务器输出数据 DataInputStream dis = new DataInputStream(connection. getInputStream()); String inputLine; while ((inputLine = dis.readLine()) != null) { System.out.println(inputLine); } dis.close();// 从服务器读数据 } }
-
HttpURLConnection:提供了对http协议的支持
Socket通信
-
服务端
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; public class Server { public static void main(String[] args) { final int PORT = 12345; try (ServerSocket serverSocket = new ServerSocket(PORT)) { System.out.println("Server is running and waiting for connections..."); // 等待客户端连接 Socket clientSocket = serverSocket.accept(); System.out.println("Client connected."); // 从客户端接收数据 BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); String message = reader.readLine(); System.out.println("Received message from client: " + message); // 关闭连接 clientSocket.close(); } catch (IOException e) { e.printStackTrace(); } } }
-
客户端
import java.io.IOException; import java.io.PrintWriter; import java.net.Socket; public class Client { public static void main(String[] args) { final String SERVER_ADDRESS = "localhost"; final int PORT = 12345; try (Socket socket = new Socket(SERVER_ADDRESS, PORT)) { System.out.println("Connected to server."); // 发送数据到服务端 //自动刷新缓冲区 PrintWriter writer = new PrintWriter(socket.getOutputStream(), true); writer.println("Hello, Server!"); // 关闭连接 socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
-
服务多个客户:调用accept等待新的连接,一旦accept返回,获得对应的socket,创建新的线程,然后调用accept,继续等待下一次连接请求
-
服务端
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.List; class ClientHandler extends Thread { private Socket clientSocket; private MultiClientServer server; private BufferedReader reader; private PrintWriter writer; public ClientHandler(Socket clientSocket, MultiClientServer server) { this.clientSocket = clientSocket; this.server = server; try { reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); writer = new PrintWriter(clientSocket.getOutputStream(), true); } catch (IOException e) { e.printStackTrace(); } } public Socket getClientSocket() { return clientSocket; } public void sendMessage(String message) { writer.println(message); } @Override public void run() { try { String username = reader.readLine(); System.out.println("New user joined: " + username); // 向所有客户端广播新用户加入的消息 server.broadcastMessage(username + " joined the chat.", this); String clientMessage; while ((clientMessage = reader.readLine()) != null) { // 向所有客户端广播收到的消息 server.broadcastMessage(username + ": " + clientMessage, this); } } catch (IOException e) { e.printStackTrace(); } finally { // 客户端断开连接,移除自身 server.removeClient(this); server.broadcastMessage("User disconnected.", this); try { clientSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } } public class MultiClientServer { private List<ClientHandler> clients = new ArrayList<>(); public static void main(String[] args) { MultiClientServer server = new MultiClientServer(); server.startServer(); } public void startServer() { final int PORT = 12345; try (ServerSocket serverSocket = new ServerSocket(PORT)) { System.out.println("Server is running and waiting for connections..."); while (true) { Socket clientSocket = serverSocket.accept(); System.out.println("Client connected: " + clientSocket); // 创建新的客户端处理线程 ClientHandler clientHandler = new ClientHandler(clientSocket, this); clients.add(clientHandler); clientHandler.start(); } } catch (IOException e) { e.printStackTrace(); } } // 向所有客户端广播消息 public void broadcastMessage(String message, ClientHandler sender) { for (ClientHandler client : clients) { // 不向消息发送者发送消息 if (client != sender) { client.sendMessage(message); } } } // 移除断开连接的客户端 public void removeClient(ClientHandler client) { clients.remove(client); System.out.println("Client disconnected: " + client.getClientSocket()); } }
-
客户端
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; public class ChatClient { public static void main(String[] args) { ChatClient client = new ChatClient(); client.startClient(); } public void startClient() { final String SERVER_ADDRESS = "localhost"; final int PORT = 12345; try (Socket socket = new Socket(SERVER_ADDRESS, PORT)) { BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in)); BufferedReader serverReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter writer = new PrintWriter(socket.getOutputStream(), true); System.out.print("Enter your username: "); String username = consoleReader.readLine(); writer.println(username); Thread messageReceiver = new Thread(() -> { try { String serverMessage; while ((serverMessage = serverReader.readLine()) != null) { System.out.println(serverMessage); } } catch (IOException e) { e.printStackTrace(); } }); messageReceiver.start(); String clientMessage; while (true) { clientMessage = consoleReader.readLine(); writer.println(clientMessage); } } catch (IOException e) { e.printStackTrace(); } } }
-
对于服务端,同一主机和端口上只能有一个监听的ServerSocket;而对于客户端,可以同时存在多个连接到相同主机和端口的 Socket。
public class test{ public class ServerCreater implements Runnable{ public void run(){ test t=new test(); int i=0; try(ServerSocket serverSocket=new ServerSocket(65432)){ while(i<5){ System.out.println("server"); Socket socket=serverSocket.accept(); Thread server=new Thread(t.new Server(socket)); server.start(); i++; } }catch(IOException e){ e.printStackTrace(); } } } public class Server implements Runnable{ private Socket socket; Server(Socket s){ socket=s; } public void run(){ try{ BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(socket.getInputStream())); String s; while((s=bufferedReader.readLine())!=null){ System.out.println("receive:"+s); } socket.close(); }catch(IOException e){ e.printStackTrace(); } } } public class Client implements Runnable{ public void run(){ try(Socket socket=new Socket("localhost", 65432)){ Thread.sleep(1000); System.out.println("client"); String s[]={"I","love","you"}; PrintWriter bufferedWriter=new PrintWriter(socket.getOutputStream(),true); for(String ss:s){ bufferedWriter.println(ss); } socket.close(); }catch(IOException|InterruptedException e){ e.printStackTrace(); } } } public static void main(String[]args)throws Exception{ test t=new test(); Thread serverCreater=new Thread(t.new ServerCreater()); serverCreater.start(); for(int i=0;i<5;i++){ Thread client=new Thread(t.new Client()); client.start(); } } }
-
-
数据报通信
-
服务端
import java.net.DatagramPacket; import java.net.DatagramSocket; public class DatagramServer { public static void main(String[] args) { final int PORT = 9876; try (DatagramSocket serverSocket = new DatagramSocket(PORT)) { System.out.println("Server is running and waiting for messages..."); byte[] receiveData = new byte[1024]; while (true) { DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); serverSocket.receive(receivePacket); String message = new String(receivePacket.getData(), 0, receivePacket.getLength()); System.out.println("Received message from client: " + message); } } catch (Exception e) { e.printStackTrace(); } } }
-
客户端
import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.util.Scanner; public class DatagramClient { public static void main(String[] args) { final String SERVER_ADDRESS = "localhost"; final int PORT = 9876; try (DatagramSocket clientSocket = new DatagramSocket()) { InetAddress serverAddress = InetAddress.getByName(SERVER_ADDRESS); Scanner scanner = new Scanner(System.in); while (true) { System.out.print("Enter a message to send to server: "); String message = scanner.nextLine(); byte[] sendData = message.getBytes(); DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, serverAddress, PORT); clientSocket.send(sendPacket); } } catch (Exception e) { e.printStackTrace(); } } }
-
远程方法调用(RMI)
程序可以方便调用远程计算机上的函数