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

Java ServerSocket详解的更多相关文章

  1. ServerSocket详解及线程阻塞_03

    ServerSocket详解构造方法ServerSocket()ServerSocket(int port)ServerSocket(int port ,int backlog)serverSocke ...

  2. Java内部类详解

    Java内部类详解 说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉.原因是平时编写代码时可能用到的场景不多,用得最多的是在有事件监听的情况下,并且即使用到也很少去总结内部类的用法.今天我们就 ...

  3. 黑马----JAVA迭代器详解

    JAVA迭代器详解 1.Interable.Iterator和ListIterator 1)迭代器生成接口Interable,用于生成一个具体迭代器 public interface Iterable ...

  4. C++调用JAVA方法详解

    C++调用JAVA方法详解          博客分类: 本文主要参考http://tech.ccidnet.com/art/1081/20050413/237901_1.html 上的文章. C++ ...

  5. Java虚拟机详解----JVM常见问题总结

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  6. [转] Java内部类详解

    作者:海子 出处:http://www.cnblogs.com/dolphin0520/ 本博客中未标明转载的文章归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置 ...

  7. Java面向对象详解

    Java面向对象详解 前言:接触项目开发也有很长一段时间了,最近开始萌发出想回过头来写写以前学 过的基础知识的想法.一是原来刚开始学习接触编程,一个人跌跌撞撞摸索着往前走,初学的时候很多东西理解的也懵 ...

  8. java 乱码详解_jsp中pageEncoding、charset=UTF -8"、request.setCharacterEncoding("UTF-8")

    http://blog.csdn.net/qinysong/article/details/1179480 java 乱码详解__jsp中pageEncoding.charset=UTF -8&quo ...

  9. java 泛型详解(普通泛型、 通配符、 泛型接口)

    java 泛型详解(普通泛型. 通配符. 泛型接口) JDK1.5 令我们期待很久,可是当他发布的时候却更换版本号为5.0.这说明Java已经有大幅度的变化.本文将讲解JDK5.0支持的新功能---- ...

随机推荐

  1. 重大改革!Python,最接近人工智能的语言~将被加入高考科目!

    就在前几天,和一位浙江省高校的信息技术老师聊天,我得到了一个震惊的消息: 明年,浙江省信息技术教材将不会在使用晦涩难懂的VB语言,而是改学更简单易懂的Python语言.也就是说, Python语言将纳 ...

  2. python基础-基本概念

    python概念介绍 python是一门动态解释型的强类型定义语言,创始人吉多·范罗苏姆(Guido van Rossum) #编译型语言 编译型:一次性将所有程序编译成二进制文件 缺点:开发效率低, ...

  3. 【Java】Map总结和源码注释

    前言 Map为一个Java中一个重要的数据结构,主要表示<key, value>的映射关系对.本文包括了相关Map数据结构的总结和源码的阅读注释. HashMap 初始化,可以选择第二个初 ...

  4. sql -- 获取商品分类的最新销售情况

    表设计: 需求: 1.先找出各个分类中销售的最新日期 select prod_class,max(sales_date) as sn from prod_sales group by prod_cla ...

  5. Java设计模式之结构模式

    一.外观模式 分析:外观模式是为子系统的一组接口提供一个统一的界面,数据库JDBC连接应用就是外观模式的一个典型例子,特点:降低系统的复杂度,增加灵活性.结果:代码示例: public class D ...

  6. 个人理解TCP中SYN Cookie

    说起SYN Cookie还是得从TCP3次握手开始说起,先给出计网的体系结构图 然后解释一下SYN,seq,ack,ACK的相关名词 SYN(建立连接) ACK(确认后全部为1) PSH(传送) FI ...

  7. 处理公共CDN突然失效的情况

    公共CDN的使用 刚开始开发我的博客时,使用的bootcdn,发现他们被黑过,虽然想骂那些“黑客”,但是我们也没办法去防范,只能从自己的网站上入手解决. 那时我还没技术解决这个问题,网上搜过,大都只提 ...

  8. JavaScript对象(一)

    Part One:对象的创建对象的创建,可以使用new Object() 或者 Object.creat(),该方法为静态函数 var foo = Object.create({x:1,y:2});  ...

  9. PHP mysql事务问题实例分析

    本文实例分析了PHP的mysql事务问题.分享给大家供大家参考,具体如下: 对于myisam数据库,可以控制事务的进行: $mysqlrl = mysql_connect ( $db_config [ ...

  10. docker 学习之路 将docker容器变为镜像并上传

    环境 ubunt 16.4 去hub.docker.com上注册一个账号,并在账号中注册一个公有public或者私有仓库private 步骤如下 如上图 点击该处进入创建docker库页面 除了名字之 ...