• 编写 Java 聊天程序并探究Socket API


    先上一张网络聊天程序运行图:

     

    功能实现的很简单,客户端输入服务器IP和端口信息连接服务器,建立连接之后,客户端和服务器就可以进行双向通信了。

    源码如下:

    client端 源代码

    import java.io.*;
    import java.net.Socket;
    import java.util.Scanner;
    
    public class Client extends Netutil  implements Runnable{
        String IPAdress;
        int port;
    
        Client(String IPAdress,int port){
            this.IPAdress=IPAdress;
            this.port=port;
        }
    
        public static void main(String[] args) {
    
            Scanner scanner = new Scanner(System.in);
            System.out.print("请输入IP地址:");
            String ip=scanner.nextLine();
            System.out.print("请输入端口号:");
            int port=scanner.nextInt();
    
            Client client1=new Client(ip,port);
    
            Thread thread1=new Thread(client1);
    
            thread1.start();
        }
    
        @Override
        public void run() {
            try {
    
                Socket s = new Socket(this.IPAdress, this.port);
                super.Oprate(s);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    }

    Server端源代码:

    import java.io.*;
    import java.net.InetAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.Scanner;
    
    public class Server extends Netutil {
    
        public static void main(String[] args) {
            new Server().Get();
        }
    
        /*进入的方法*/
        public void Get() {
            try {
                ServerSocket serverSocket = new ServerSocket(4432);
                InetAddress inetAddress = InetAddress.getLocalHost();
    
                // System.out.println("开启服务器");
                System.out.println("地址:" + inetAddress.getHostAddress() + "端口:" + 4432);
                Socket accept;
                while (true) {
                    accept = serverSocket.accept();
                    //System.out.println("主机"+accept.getRemoteSocketAddress()+"连接服务器");
    
                    Thread hander = new Thread(new Handler(accept));
                    hander.start();
    
    
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    
        /**
         * 内部处理类
         */
        class Handler extends Netutil implements Runnable {
            Socket socket;
    
            public Handler(Socket socket) {
                this.socket = socket;
            }
    
            @Override
            public void run() {
                try {
                    super.Oprate(socket);
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
            }
        }
    
    }

    聊天功能实现类:

    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.net.Socket;
    import java.util.Scanner;
    
    public class Netutil {
    
        public void Oprate(Socket s) throws IOException {
            DataInputStream dataInputStream = new DataInputStream(s.getInputStream());
            DataOutputStream dataOutputStream = new DataOutputStream(s.getOutputStream());
    
            new Thread() {
                @Override
                public void run() {
                    String line;
                    String content = "";
                    while (true) {
                        try {
                            Thread.sleep(100);
                            content = "";
                            while (!((line = dataInputStream.readUTF()).equals("EOF"))) {
                                content = content + line;
                                // System.out.println(line);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
    
                        System.out.println("收到:" + content);
                    }
                }
            }.start();
    
    
            Scanner scanner = new Scanner(System.in);
            String message;
    
            while (true) {
                message = scanner.nextLine();
                if (message.equals("#qiut")) break;
                dataOutputStream.writeUTF(message);
                dataOutputStream.writeUTF("EOF");
                dataOutputStream.flush();
            }
            dataInputStream.close();
            dataOutputStream.close();
            s.close();
        }
    
    
    }

    聊天程序的流程图如下:

    但是,光会用JAVA编写聊天程序显然是不行的,让我们深入其API探讨一下socket的建立过程。

    在程序中,客户端初始化了一个socket连接,用来连接服务器,

     

    调试进入之后,调用的是如下构造方法

    上图中的构造方法在参数处理之后,调用了自身的其他构造,其中,下图的构造方法中,address为服务器端口地址,localAddr为自身端口地址,stream为是否要打开传输流。

     

    在构造函数中,首先调用的是setImpl( )方法,调试跟踪发现,impl采用的是

    Impl=new SocksSocketimpl()构造的,impl是SocketImpl类型,实现了SocketOptions接口,用来描述socket的参数。

     

    再往下,看看SocksSocketImpl是如何构造的。

     

    SocksSocketImpl构造函数为空方法,但是他继承了PlainSocketImpl类,在看看PlainSocketimpl类的构造方法,其中构造了DualStackPlainSocketImpl对象,DualStackPlainSocketImpl对象表示双向栈的Socket对象,为带有双向流socket.

    DualStackPlainSocketImpl构造函数如下:

     

    在看完了setImpl()函数调用的,过程之后,继续往下走,在Socket函数中,接下来调用了createImpl()方法,方法里面调用了create()方法。

     

    在那之后,在try catch块中调用了DualStackPlainSocketImpl对象的bind和Conect方法,DualStackPlainSocketImpl对象中的的bind和Conect方法,调用的是本地的方法库,调用的是C中的bind和connect方法,C语言中的bind方法和connect方法在Java API中就不在深究了。

  • 相关阅读:
    数组——遍历
    数组常用方法——汇总
    箭头函数
    overflow:auto产生的滚动条在安卓系统下能平滑滚动,而在ios下滚动不平滑
    浅谈过载保护
    tornado中使用torndb,连接数过高的问题
    如何开启并查看博客园MetaWeblog接口的xml-RPC协议访问地址
    aardio陷阱(转)
    aardio获取公网IP地址代码
    sql常用函数学习笔记整理
  • 原文地址:https://www.cnblogs.com/AmosYang6814/p/12015356.html
Copyright © 2020-2023  润新知