首页 > 代码库 > java点滴之ServerSocket的使用

java点滴之ServerSocket的使用

一概念

serversocket实现了服务端的socket,一个服务端的socket等待从网络上发来的请求,并基于这个请求作出
响应的操作,并作出回应结果。

serversocket 建立的是socket的服务端,socket建立的是客户端。最主要构造方法:


public ServerSocket():创建一个未绑定任何端口的套接字,通过该方法创建的 ServerSocket 不与任何端口绑定, 接下来还需要通过 bind() 方法与特定端口绑定. 这个默认构造方法的用途是, 允许服务器在绑定到特定端口之前, 先设置ServerSocket 的一些选项. 因为一旦服务器与特定端口绑定, 有些选项就不能再改变了.

 public ServerSocket(int port):创建一个绑定指定端口的套接字,0代表端口号是自动分配的,并默认最大只允许

50个连接请求,在请求没有被accept()之前,如果Client再请求连接,就会被Server拒绝。

ServerSocket(int port, int backlog, InetAddress bindAddr):参数:指定端口号,最大连接数,bindAddr显式指定服务器要绑定的IP地址.

setReuseAddress(true)方法:

可以允许多个socket
绑定到相同的IP地址和端口,那么发送到此IP地址和端口的数据能够被复制到多个socket,
也就是说能够实现多播的功能。(我知道多播程序用MutilcastSocket类) ,
setReuseAddress() 必须在socket绑定到端口之前调用才有效,
 如果端口忙,但TCP状态位于 TIME_WAIT ,可以重用 端口。如果端口忙,而TCP状态位于其他状态,重用端口时依旧得到一个错误信息, 抛出“Address already in use: JVM_Bind”。如果你的服务程序停止后想 立即重启,不等60秒,而新套接字依旧 使用同一端口,此时 SO_REUSEADDR 选项非常有用。必须意识到,此时任何非期 望数据到达,都可能导致服务程序反应混乱,不过这只是一种可能,事实上很不可能。

二服务端处理线程提供的方法

1.服务线程的开启
    public synchronized boolean start() {
        mHttpServerThread = new Thread(this);
        mHttpServerThread.setName("HTTP Accept Thread" + ":" + mBindPort);
        // httpServerThread.setPriority(Thread.MIN_PRIORITY);
        mHttpServerThread.setDaemon(true);
        mHttpServerThread.setPriority(Thread.MAX_PRIORITY);
        bHttpServerThreadFlag = true;
        mHttpServerThread.start();
        return true;
    }

2.业务方法
public void run() {
        if (isOpened() == false)
            return;

        // Thread Pool
        ExecutorService exeutor = Executors.newCachedThreadPool();
        Thread thisThread = Thread.currentThread();

        DLog.i(mTAG, "run", "http server started!!!!");

        while (bHttpServerThreadFlag && mHttpServerThread != null && thisThread != null
                && mHttpServerThread.equals(thisThread)) {
            Thread.yield();
            Socket sock = null;

            try {
                while (HTTPServerThread.usedServerSocket > HTTPServerThread.MAX_SERVER_SOCKET) {
                    Thread.yield();
                }

                synchronized (mAcceptSocketList) {
                    sock = accept();
                    if (sock != null) {
                        // CTT 2.0
                        // accepted socket is added to arrayList using
                        // WeakReference
                        // the socket SHOULD be closed when http server is
                        // stopped
                        mAcceptSocketList.add(new WeakReference<Socket>(sock));
                        exeutor.execute(new HTTPServerThread(this, sock));

                        ++HTTPServerThread.usedServerSocket;
                    }
                }

                if (isOpened() == false)
                    break; // http server is closed.
            } catch (Exception e) {
                if (sock != null) {
                    try {
                        sock.close();
                    } catch (IOException e1) {
                        DLog.w(mTAG, "run", "run - IOException", e);
                    }
                }
                DLog.w(mTAG, "run", "run - IOException", e);
                continue;
            }
        }

        // Thread Pool
        exeutor.shutdown();
        DLog.i(mTAG, "run", "http server stopped!!!!");

    }


3.创建
 public boolean open(int port) {
        if (mServerSock != null)
            return true;
        try {
            mBindPort = port;

            // Debug.error("HTTPServer", "Address: " + MediaServer.ipAddress +
            // String.valueOf(port));
            mServerSock = new ServerSocket(mBindPort, 512);
            mServerSock.setSoTimeout(HTTP.DEFAULT_TIMEOUT * 1000 + 5000);
            mServerSock.setReuseAddress(true);
        } catch (IOException e) {
            DLog.w(mTAG, "open", "Open - IOException", e);
            return false;
        }
        return true;
    }

4.阻塞接收请求
public Socket accept() {
        Socket sock = null;
        if (mServerSock == null || mServerSock.isClosed())
            return null;
        try {
            sock = mServerSock.accept();
            sock.setSoTimeout(HTTP.DEFAULT_TIMEOUT * 1000 + 5000); // add margin
            sock.setReceiveBufferSize(HTTP.DEFAULT_CHUNK_SIZE);
            sock.setSendBufferSize(HTTP.DEFAULT_CHUNK_SIZE);
            // sock.setSoLinger(true, HTTP.DEFAULT_TIMEOUT);
            DLog.d(mTAG, "open", "accept :" + String.valueOf(sock.getSendBufferSize()));
            return sock;
        } catch (SocketTimeoutException e1) {
            return null;
        } catch (Exception e) {
            try {
                if (sock != null)
                    sock.close();
            } catch (IOException e1) {
                e = e1;
            }

            DLog.w(mTAG, "open", "accept Exception :" + e.toString(), e);

            return null;
        }
    }
5.服务线程的停止
 public synchronized boolean stop() {
        close();

        bHttpServerThreadFlag = false;

        DLog.i(mTAG, "stop", "Wait start for finishing thread !!!");
        if (mHttpServerThread != null && mHttpServerThread.isAlive()) {
            try {
                mHttpServerThread.join();
            } catch (InterruptedException e) {
                DLog.w(mTAG, "stop", "Thread Join InterruptedException", e);
            }
        }
        DLog.i(mTAG, "stop", "Wait done for finishing thread !!!");

        mHttpServerThread = null;

        // CTT 2.0
        // Accepted socket SHOULD be closed

        synchronized (mAcceptSocketList) {
            for (WeakReference<Socket> sockRef : mAcceptSocketList) {
                try {
                    Socket sock = sockRef.get();
                    if (sock != null) {
                        sock.close();
                    }
                } catch (IOException e) {
                    DLog.w(mTAG, "stop", "Error: socket - IOException", e);
                }
            }

            mAcceptSocketList.clear();
        }

        return true;
    }
6.服务线程的关闭
public boolean close() {
        if (mServerSock == null)
            return true;
        try {
            mServerSock.close();
        } catch (Exception e) {
            DLog.w(mTAG, "open", "Close  - Exception :", e);
            return false;
        } finally {
            mServerSock = null;
            mBindPort = 0;
        }
        return true;
    }