socket網絡編程登錄實現及多客戶端和服務端的數據交互
阿新 • • 發佈:2019-03-27
取數據 sin 一個用戶 run set inf exceptio 反序列化 ram
一.TCP/IP
客戶端
package com.demo.entity; import java.io.Serializable; public class UserInfo implements Serializable { /** * */ private static final long serialVersionUID = 1L; /** * */ private String username; private String password; publicString getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
package com.demo.entity; import java.io.BufferedInputStream; import java.io.ObjectOutputStream; import java.net.Socket; import java.util.Scanner; public class UserClient { private static int port = 5566; private static String host = "localhost"; public static voidmain(String[] args) { Socket socket = null; // 創建掃描器對象 Scanner sc = null; try { sc = new Scanner(System.in); // 創建一個客戶端的Socket對象,獲取服務端輸入和輸出流對象 socket = new Socket(host, port); ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); System.out.println("請輸入賬號:"); String userName = sc.nextLine(); System.out.println("請輸入密碼:"); String password = sc.nextLine(); // 封裝一個用戶對象 UserInfo user = new UserInfo(); user.setPassword(password); user.setUsername(userName); // 序列化到輸出流中 oos.writeObject(user); // 釋放流資源 oos.flush(); // 讀取從服務端返回的數據 BufferedInputStream bis = new BufferedInputStream(socket.getInputStream()); byte[] buffer = new byte[1024]; int len = 0; while ((len = bis.read(buffer)) != -1) { String content = new String(buffer, 0, len); System.out.println("登錄結果:"+content); } socket.shutdownOutput(); socket.shutdownInput(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (socket != null) { socket.close(); } } catch (Exception e2) { e2.printStackTrace(); } sc.close(); } } }
服務器端
package com.demo.entity; import java.io.Serializable; public class UserInfo implements Serializable { /** * */ private static final long serialVersionUID = 1L; /** * */ private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
package com.demo.entity; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.net.ServerSocket; import java.net.Socket; /** * 1、服務器端序列化的對象全名稱必須和反序列化的全名稱完全一致 * 2、序列化和反序列化對象的序列化Id必須一致 * 3、在網絡編程中需要在網絡中傳輸對象必須實現Serializable。 * 4、釋放資源的時候流不要使用close方法關閉。 * @author Administrator * */ public class UserServer { private static int port = 5566; public static void main(String[] args) { ServerSocket serverSocket = null; Socket socket = null; while (true) { try { serverSocket = new ServerSocket(port); System.out.println("等待客戶端連接"); // 服務器socket, 可以獲取到客戶端對應輸入流和輸出流對象 socket = serverSocket.accept(); System.out.println("端口號:"+socket.getPort()); System.out.println(socket.getInetAddress().getCanonicalHostName() + "連接到了服務器"); // 創建一個反序列化流 ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); // 返回客戶端序列化的對象 UserInfo user = (UserInfo) ois.readObject(); System.out.println(user.getPassword() + "---" + user.getUsername()); // 獲取賬號和密碼 String account = user.getUsername(); String password = user.getPassword(); // 創建輸出流 BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream()); // 判斷轉換和密碼是否正確 if ("admin".equals(account) && "123".equals(password)) { bos.write("登錄成功".getBytes()); } else { bos.write("登錄失敗".getBytes()); } bos.flush(); bos.close(); ois.close(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (serverSocket != null) { serverSocket.close(); } } catch (IOException e) { e.printStackTrace(); } } } } }
package com.demo.entity; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 1、服務器端序列化的對象全名稱必須和反序列化的全名稱完全一致 * 2、序列化和反序列化對象的序列化Id必須一致 * 3、在網絡編程中需要在網絡中傳輸對象必須實現Serializable。 * 4、釋放資源的時候流不要使用close方法關閉。 * @author Administrator * */ public class UserServerM { private static int port = 5555; public static void main(String[] args) throws IOException { int clientNo = 1; ServerSocket serverSocket = new ServerSocket(port); // 創建一個緩存線程池 ExecutorService pool = Executors.newCachedThreadPool(); try { while (true) { Socket socket = serverSocket.accept(); pool.execute(new SingleServer(clientNo++, socket)); } } catch (Exception e) { e.printStackTrace(); } finally { pool.shutdown(); if (!serverSocket.isClosed()) { serverSocket.close(); } } } } class SingleServer implements Runnable { private int clientNo; // 客戶端編號 private Socket socket; public SingleServer(int clientNo, Socket socket) { this.clientNo = clientNo; this.socket = socket; } @Override public void run() { System.out.println("第"+clientNo+"客戶端連接到了服務器"); System.out.println("port:"+socket.getPort()); System.out.println(socket.getInetAddress().getCanonicalHostName() + "連接到了服務器"); try { // 創建一個反序列化流 ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); // 返回客戶端序列化的對象 UserInfo user = (UserInfo) ois.readObject(); System.out.println(user.getPassword() + "---" + user.getUsername()); // 獲取賬號和密碼 String account = user.getUsername(); String password = user.getPassword(); // 創建輸出流 BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream()); // 判斷轉換和密碼是否正確 if ("admin".equals(account) && "123".equals(password)) { bos.write("登錄成功".getBytes()); } else { bos.write("登錄失敗".getBytes()); } bos.flush(); bos.close(); ois.close(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (!socket.isConnected()) { socket.close(); } } catch (Exception e2) { e2.printStackTrace(); } } } }
二.UDP
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; /* * 客戶端 */ public class UDPClient { public static void main(String[] args) throws IOException { /* * 向服務器端發送數據 */ // 1.定義服務器的地址、端口號、數據 InetAddress address = InetAddress.getByName("localhost"); int port = 8800; byte[] data = "用戶名:admin;密碼:123".getBytes(); // 2.創建數據報,包含發送的數據信息 DatagramPacket packet = new DatagramPacket(data, data.length, address, port); // 3.創建DatagramSocket對象 DatagramSocket socket = new DatagramSocket(); // 4.向服務器端發送數據報 socket.send(packet); /* * 接收服務器端響應的數據 */ // 1.創建數據報,用於接收服務器端響應的數據 byte[] data2 = new byte[1024]; DatagramPacket packet2 = new DatagramPacket(data2, data2.length); // 2.接收服務器響應的數據 socket.receive(packet2); // 3.讀取數據 String reply = new String(data2, 0, packet2.getLength()); System.out.println("我是客戶端,服務器說:" + reply); // 4.關閉資源 socket.close(); } }
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; /* * 服務器端,實現基於UDP的用戶登陸 */ public class UDPServer { public static void main(String[] args) throws IOException { /* * 接收客戶端發送的數據 */ // 1.創建服務器端DatagramSocket,指定端口 DatagramSocket socket = new DatagramSocket(8800); // 2.創建數據報,用於接收客戶端發送的數據 byte[] data = new byte[1024];// 創建字節數組,指定接收的數據包的大小 DatagramPacket packet = new DatagramPacket(data, data.length); // 3.接收客戶端發送的數據 System.out.println("****服務器端已經啟動,等待客戶端發送數據"); socket.receive(packet);// 此方法在接收到數據報之前會一直阻塞 // 4.讀取數據 String info = new String(data, 0, packet.getLength()); System.out.println("我是服務器,客戶端說:" + info); /* * 向客戶端響應數據 */ // 1.定義客戶端的地址、端口號、數據 InetAddress address = packet.getAddress(); int port = packet.getPort(); byte[] data2 = "歡迎您!".getBytes(); // 2.創建數據報,包含響應的數據信息 DatagramPacket packet2 = new DatagramPacket(data2, data2.length, address, port); // 3.響應客戶端 socket.send(packet2); // 4.關閉資源 socket.close(); } }
socket網絡編程登錄實現及多客戶端和服務端的數據交互