java点滴之ServerSocket的使用
一概念
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
选项非常有用。必须意识到,此时任何非期 望数据到达,都可能导致服务程序反应混乱,不过这只是一种可能,事实上很不可能。
二服务端处理线程提供的方法
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!!!!");
} 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;
}