socket网络编程登录实现及多客户端和服务端的数据交互

一.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();
    }
}

猜你喜欢

转载自www.cnblogs.com/sunBinary/p/10604536.html