java的serversocket_Java ServerSocket详解
ServerSocket
构造方法
ServerSocket serverSocket = new ServerSocket();
ServerSocket();//无参数
ServerSocket(int port);//指定端口
ServerSocket(int port,int backlog);//指定端口、队列数
ServerSocket(int port,int backlog,InetAddress bindAddr);//指定端口、队列数、绑定IP
注:当port为0时,随机分配空闲端口。
无参数绑定端口
serverSocket.bind(SocketAddress endpoint);//指定端口
serverSocket.bind(SocketAddress endpoint,int backlog)//指定端口、队列数
ServerSocket选项
SO_TIMEOUT:等待客户连接的超时时间
serverSocket.setSoTimeout(int timeout);//设置(单位为毫秒,为0,则永不超时)
serverSocket.getSoTimeout();//查看超时时间
SO_REUSEADDR:是否允许重用服务器所绑定的地址(需在连接前设置)
serverSocket.setResuseAddress(boolean on);//设置
serverSocket.getResuseAddress();//查看是否开启
SO_RCVBUF:接收数据的缓冲区大小
serverSocket.setReceiveBufferSize(int size);//设置
serverSocket.getReceiveBufferSize();//查看缓冲区大小
设定连接时间、延迟和带宽
参数(相对权重)
三个参数之间的相对大小决定相应参数的相对重要性。
connectionTime:最少时间建立连接
latency:最小延迟
bandwidth:最高带宽
serverSocket.setPerformancePreferences(int connectionTime,int latency,int bandwidth);//设置
ServerSocket信息
serverSocket.getInetAddress();//获取服务器绑定的IP
serverSocket.getLocalPort();//获取服务器绑定的端口
多线程
为每一个连接创建一个线程
重写Runnable方法
Handler.java
package Network_3;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
public class Handler implements Runnable {
private Socket socket = null;//初始化Socket
public Handler(Socket socket) {
this.socket = socket;//传入参数
}
/*
*输出流
*/
public PrintWriter getWriter(Socket socket) throws IOException {
OutputStream socketOut = socket.getOutputStream();
return new PrintWriter(socketOut,true);
}
/*
*输入流
*/
public BufferedReader getReader(Socket socket) throws IOException {
InputStreamReader socketIn = new InputStreamReader(socket.getInputStream());
return new BufferedReader(socketIn);
}
//加工信息
public String Echo(String msg) {
return "Echo:"+msg;
}
public void run() {
try {
System.out.println("New Connection "+socket.getInetAddress()+":"+socket.getPort());//打印新连接信息
BufferedReader br = getReader(socket);//输入流
PrintWriter pw = getWriter(socket);//输出流
String msg = null;//初始化msg
while((msg = br.readLine()) != null) {//循环读取一行信息
System.out.println(msg);//打印信息
pw.println(Echo(msg));//将信息加工发送回客户端
if(msg.equals("exit")) {//结束条件
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(socket != null) {//如有连接,关闭
socket.close();
}
}catch (Exception e) {
e.printStackTrace();
}
}
}
}
Server.java
package Network_3;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
private int port = 8000;//初始化port
private ServerSocket serverSocket = null;//初始化ServerSocket
public Server() {
try {
serverSocket = new ServerSocket(port);//启动服务端
System.out.println("Server Up!");
} catch (IOException e) {
System.out.println("Server Up Error!");
}
}
public void service() {
while(true) {
Socket socket = null;//初始化Socket
try {
socket = serverSocket.accept();//监听连接队列
Thread workThread = new Thread(new Handler(socket)); //创建线程
workThread.start();//启动线程
}catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new Server().service();
}
}
Client.java
package Network_3;
import java.net.*;
import java.io.*;
public class Client {
/*
* 参数初始化
*/
private String host = "127.0.0.1";
private int port = 8000;
private Socket socket;
/*
* 建立连接
*/
public Client() throws IOException {
socket = new Socket(host,port);
}
/*
* 输出流
*/
private PrintWriter getWriter(Socket socket) throws IOException {
OutputStream socketOut = socket.getOutputStream();
return new PrintWriter(socketOut,true);
}
/*
* 输入流
*/
private BufferedReader getReader(Socket socket) throws IOException {
InputStreamReader socketIn = new InputStreamReader(socket.getInputStream());
return new BufferedReader(socketIn);
}
/*
* 客户程序
*/
public void Talk() {
try {
BufferedReader br = getReader(socket);
PrintWriter pw = getWriter(socket);
BufferedReader localReader = new BufferedReader(new InputStreamReader(System.in));
String msg = null;
while((msg = localReader.readLine()) != null) {
pw.println(msg);
System.out.println(br.readLine());
if(msg.equals("exit")) {
break;
}
}
}catch (Exception e) {
e.printStackTrace();
}finally {
try {
socket.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws UnknownHostException, IOException {
new Client().Talk();
}
}
使用JDK类库提供的线程池
java.util.concurrent包提供
Server.java
package Network_3;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Server {
private int port = 8000;//初始化port
private ServerSocket serverSocket = null;//初始化ServerSocket
private ExecutorService executorService = null;//初始化线程池
private final int POOL_SIZE = 4;//单个CPU的线程数
public Server() throws IOException {
serverSocket = new ServerSocket(port);
executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * POOL_SIZE);//创建线程池,Runtime.getRuntime().availableProcessors()用于返回当前工作环境的CPU数,将CPU数乘单个CPU线程数,得到最终的总线程数。
System.out.println("Server Up");
}
public void service() {
while(true) {
Socket socket = null;
try {
socket = serverSocket.accept();
executorService.execute(new Handler(socket));//Handler与上面的一样
}catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
new Server().service();
}
}
注意事项
死锁
建议:尽量减少任务之间的依赖。
系统资源不足
建议:根据系统性能设定线程数,回收机制。
并发错误
建议:使用成熟的线程技术。
线程泄露
建议:执行线程任务时,减少与用户的交互(使用超时机制)。
任务过载
建议:控制线程等待队列中的线程数。
关闭服务器
开放一个管理服务器端口,启动守护线程,供管理程序连接,当发送特定字符时,服务器停止向线程池添加任务并等待任务执行完毕或超时,关闭服务程序。
Server.java
package Network_3;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
public class Server {
private int port = 8000;//服务端口
private ServerSocket serverSocket = null;//服务Socket
private ExecutorService executorService = null;//线程池
private final int POOL_SIZE = 4;//单个CPU的线程数
private int portForShutdown = 8001;//守护线程端口
private ServerSocket serverSocketForShutdown = null;//守护Socket
private boolean isShutdown = false;//服务器是否关闭
private Thread shutDownThread = new Thread() {//负责关闭服务器的线程
public void start() {
this.setDaemon(true);//设置为守护线程(后台线程)
super.start();
}
public void run() {
while(!isShutdown) {
Socket socketForShutdown = null;
try {
socketForShutdown = serverSocketForShutdown.accept();//开启监听
//获取输入流
BufferedReader br = new BufferedReader(new InputStreamReader(socketForShutdown.getInputStream()));
String command = br.readLine();//读取一行字符
if(command.equals("shutdown")) {//判断是否符合指定字符
long beginTime = System.currentTimeMillis();//开始计数
//输出流输出字符
socketForShutdown.getOutputStream().write("Server Shutdowning\r\n".getBytes());
//服务器关闭
isShutdown = true;
//不再向线程池添加新线程
executorService.shutdown();
//所有任务是否已完成
while(!executorService.isTerminated()) {
//设置线程池中任务的完成超时时间
executorService.awaitTermination(30, TimeUnit.SECONDS);
}
//关闭服务器
serverSocket.close();
long endTime = System.currentTimeMillis();//结束计数
//输出流输出字符
socketForShutdown.getOutputStream().write(("Server Shutdown\r\nTime:"+(endTime-beginTime)+"ms\r\n").getBytes());
//关闭守护线程
socketForShutdown.close();
serverSocketForShutdown.close();
}else {
//不符合特定字符
socketForShutdown.getOutputStream().write("Error".getBytes());
socketForShutdown.close();
}
}catch (Exception e) {
e.printStackTrace();
}
}
}
};
public Server() throws IOException {
//创建Socket
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(60000);//设置超时时间
//创建守护Socket
serverSocketForShutdown = new ServerSocket(portForShutdown);
//创建线程池
executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * POOL_SIZE);
//运行守护线程
shutDownThread.start();
System.out.println("Server Up");
}
public void service() {
while(!isShutdown) {
Socket socket = null;
try {
socket = serverSocket.accept();
socket.setSoTimeout(60000);
executorService.execute(new Handler(socket));
}catch (SocketTimeoutException e) {
System.out.println("Client Timeout");
}catch (RejectedExecutionException e) {
try {
if(socket != null) {
socket.close();
}
}catch (IOException x) {
return;
}
}catch (SocketException e) {
if(e.getMessage().indexOf("socket closed") != -1) {
return;
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
new Server().service();
}
}
AdminClient.java
package Network_3;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
public class AdminClient {
public static void main(String[] args) {
Socket socket = null;
try {
socket = new Socket("localhost", 8001);
OutputStream socketOut = socket.getOutputStream();
socketOut.write("shutdown\r\n".getBytes());
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String msg = null;
while((msg = br.readLine()) != null) {
System.out.println(msg);
}
}catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(socket != null) {
socket.close();
}
}catch (Exception e) {
e.printStackTrace();
}
}
}
}