1. 程式人生 > >socket網絡編程登錄實現及多客戶端和服務端的數據交互

socket網絡編程登錄實現及多客戶端和服務端的數據交互

取數據 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;
    
    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.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 void
main(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網絡編程登錄實現及多客戶端和服務端的數據交互