ServerSocket的介绍
导语
仅仅只有Socket类是不足以编写服务器的。要创建一个Socket,你需要知道希望连接哪个Internet主机。编写服务器程序时,无法预先了解哪个主机会联系你,即使确实知道,你也不清楚那个主机希望何时与你联系。对于服务器端的Socket,java提供了一个ServerSocket类表示服务器Socket。从技术上讲,服务器Socket在服务器上运行,监听入站TCP连接,每个服务器Socket监听服务器机器上的一个特定端口。当有个客户端尝试连接这个端口时,服务器就被唤醒,协商建立客户端和服务器之间的连接,并返回一个常规的Socket对象,表示两台主机之间的Socket。换句话说,服务器等待连接,客户端发起连接,一旦ServerSocket建立了连接,服务器会使用一个常规的Socket对象向客户端发送数据。
使用ServerSocket
ServerSocket类包含了服务器端Socket所需的全部内容。其中包括构造ServerSocket对象,指定端口监听连接的方法,配置各个服务器Socket选项的方法,以及其它一些常见的方法。下面是服务器程序的基本生命周期:
- 使用一个ServerSocket()构造函数在一个特定端口创建一个新的ServerSocket
- ServerSocket使用其accept()方法监听这个端口的入站连接。accept()会一直阻塞,直到一个客户端尝试建立连接,此时accept()将会返回一个连接客户端和服务器的Socket对象
- 根据服务器的类型,会调用Socket的getInputSteam()方法或getOutputSteam()方法,或者这两个方法都调用,以获得与客户端通信的输入和输出流
- 服务器和客户端根据已协商的协议交互
- 服务器或客户端关闭连接
- 服务器返回到步骤2,等待下一次连接
简单的daytime服务器
public static void main(String[] args) {
try (ServerSocket server = new ServerSocket(13)) {
while (true) {
try (Socket conn = server.accept()) {
Writer out = new OutputStreamWriter(conn.getOutputStream());
out.write(new Date().toString());
out.flush();
out.close();
conn.close();
} catch (IOException e) {}
}
} catch (IOException e) {
e.printStackTrace();
}
}
多线程服务器
操作系统会把指向某个特定端口的入站连接请求存储在一个先进先出的队列中。默认地,Java会将这个队列的长度设置为50,但不同的操作系统会有所不同。有些操作系统有一个最大队列长度,例如,在FreeBSD上,默认的最大队列长度为128。在构建ServerSocket时可以指定这个值,但是这个值不能超过操作系统设置的值。当队列中的连接达到最大容量时,主机会拒绝这个端口上额外的连接,直到队列腾出新的位置为止。为了尽快能够处理队列中的连接,可以采用多线程的方式来处理每个socket。
package com.dy.xidian;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class PooledDaytimeServer {
private final static int PORT = 13;
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(50);
try (ServerSocket server = new ServerSocket(PORT)) {
while (true) {
try {
Socket conn = server.accept();
pool.execute(new DaytimeTask(conn));
} catch (IOException e) {}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class DaytimeTask implements Runnable {
public Socket conn;
public DaytimeTask(Socket _conn) {
conn = _conn;
}
@Override
public void run() {
try {
Writer out = new OutputStreamWriter(conn.getOutputStream());
out.write(new Date().toString());
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (conn != null)
try {
conn.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
从客户端读取数据
echo协议是最简单的交互式TCP服务之一。客户端打开指向echo服务器端口7的socket,并发送数据。服务器将数据发回。这个过程一直继续,直到客户端关闭连接为止。echo协议很有用,可以测试网络,确保数据没有被有问题的路由器或防火墙所破坏。下面的代码中使用NIO中的技术,如果对NIO不了解请移步
package com.dy.xidian;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
public class PooledDaytimeServer {
private final static int PORT = 7;
public static void main(String[] args) {
ServerSocketChannel serverChannel;
Selector selector;
try {
serverChannel = ServerSocketChannel.open();
ServerSocket server = serverChannel.socket();
InetSocketAddress address = new InetSocketAddress(PORT);
server.bind(address);
serverChannel.configureBlocking(false);
selector = Selector.open();
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
} catch (IOException e) {
e.printStackTrace();
return;
}
while (true) {
try {
selector.select();
} catch (IOException e) {
e.printStackTrace();
break;
}
Set<SelectionKey> readyKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = readyKeys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
iterator.remove();
try {
if (key.isAcceptable()) {
ServerSocketChannel server = (ServerSocketChannel) key.channel();
SocketChannel client = server.accept();
System.out.println("Accepted connection from " + client);
client.configureBlocking(false);
SelectionKey clientKey = client.register(selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ);
ByteBuffer buffer = ByteBuffer.allocate(100);
clientKey.attach(buffer);
}
if (key.isReadable()) {
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer output = (ByteBuffer) key.attachment();
client.read(output);
}
if (key.isWritable()) {
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer output = (ByteBuffer) key.attachment();
output.flip();
client.write(output);
output.compact();
}
} catch (IOException e) {
key.cancel();
try {
key.channel().close();
} catch (IOException e1) {}
}
}
}
}
}
关闭服务器Socket
使用完一个服务器Socket,就应该将其关闭。但不要把关闭ServerSocket与关闭Socket混淆。关闭ServerSocket会释放本地主机的一个端口,允许另一个服务可以绑定这个端口,并且它还会中断该ServerSocket已经接受的目前处于打开状态的所有Socket。关闭ServerSocket基本使用下面的流程:
ServerSocket server = null;
try {
server = new ServerSocket(port);
} finally {
if (server != null) {
try {
server.close();
} catch (IOException e) {}
}
}
构造服务器Socket
创建一个Socket监听80端口
ServerSocket httpd = new ServerSocket(80);
如果主机上有多个IP地址,我们只想监听特定的IP地址上请求(50表示入栈连接的最大个数)
InetAddress local = InetAddress.getByName("192.168.0.100");
ServerSocket httpd = new ServerSocket(80, 50, local);
ServerSocket的介绍的更多相关文章
- TCP 通信
一.TCP与UDP的区别 二.ServerSocket与Socket 1 ServerSocket 以上介绍的几个构造方法中,第二个构造方法最常用. 2.Socket import java.io.* ...
- Java ServerSocket的服务端代码介绍
转自:http://developer.51cto.com/art/201003/190007.htm 所谓Java ServerSocket通常也称作"套接字",有不少的时候需要 ...
- python select网络编程详细介绍
刚看了反应堆模式的原理,特意复习了socket编程,本文主要介绍python的基本socket使用和select使用,主要用于了解socket通信过程 一.socket模块 socket - Low- ...
- SSL介绍与Java实例
有关SSL的原理和介绍在网上已经有不少,对于Java下使用keytool生成证书,配置SSL通信的教程也非常多.但如果我们不能够亲自动手做一个SSL Sever和SSL Client,可能就永远也不能 ...
- PhoneGap 在 Android 上的插件开发方法介绍
移动应用开发已经成为软件开发的一个重要方向,但是移动开发面临的一个重要问题就是跨平台的问题.PhoneGap 作为一个多平台的软件开发框架,提供了一次编写多个平台的运行.目前已经支持多达 6 个移动平 ...
- 【转】Android bluetooth介绍(二): android blueZ蓝牙代码架构及其uart 到rfcomm流程
原文网址:http://blog.sina.com.cn/s/blog_602c72c50102uzoj.html 关键词:蓝牙blueZ UART HCI_UART H4 HCI L2CAP ...
- Java 语言中 Enum 类型的使用介绍
Enum 类型的介绍 枚举类型(Enumerated Type) 很早就出现在编程语言中,它被用来将一组类似的值包含到一种类型当中.而这种枚举类型的名称则会被定义成独一无二的类型描述符,在这一点上和常 ...
- Java[4] Jetty工作原理介绍(转)
转自:https://www.ibm.com/developerworks/cn/java/j-lo-jetty/ Jetty 的工作原理以及与 Tomcat 的比较 Jetty 应该是目前最活跃也是 ...
- Socket介绍
一 socket协议 Socket协议的形象描述 socket的英文原义是“孔”或“插座”.在这里作为4BDS UNIX的进程通信机制,取后一种意思.socket非常类似于电话插座.以一个国家级电话网 ...
随机推荐
- 浏览器自动刷新——基于Nodejs的Gulp LiveReload与VisualStudio完美结合。
本文版权桂博客园和作者吴双共同所有,转载和爬虫请注明原文地址 http://www.cnblogs.com/tdws/p/6016055.html 写在前面 大家好我是博客园的蜗牛,博客园的蜗牛就是我 ...
- 了解java注解
类似于下面这样的就是注解 注解可以在类上,成员变量上,方法上等 假如有2个注解是这样的:(其中的Author和Date) 那么这2个注解的定义就是这样的: Author注解: Date注解: 可以看到 ...
- struts2类型转换
1. Struts2中的类型转换 我们知道通过HTTP提交到后台的数据,都是字符串的形式,而我们需要的数据类型当然不只字符串类型一种.所以,我们需要类型转换! 在Struts2中,类型转换的概念除了用 ...
- jQuery的$.ajax
在介绍JSONP之前,先简单的介绍一些JSON.JSON是JavaScript Object Notation的缩写,是一种轻量的.可读的基于文本的数据交换开放标准.源于JavsScript编程语言中 ...
- 设计模式-代理模式(Proxy Model)
文 / vincentzh 原文连接:http://www.cnblogs.com/vincentzh/p/5988145.html 目录 1.写在前面 2.概述 3.目的 4.结构组成 5.实现 5 ...
- 【JS基础】算法
Math 对象 Math.sqrt() //返回一个数的平方根
- RESTful Api 身份认证安全性设计
REST是一种软件架构风格.RESTful Api 是基于 HTTP 协议的 Api,是无状态传输.它的核心是将所有的 Api 都理解为一个网络资源.将所有的客户端和服务器的状态转移(动作)封装到 H ...
- canvas贝塞尔曲线
贝塞尔曲线 Bézier curve(贝塞尔曲线)是应用于二维图形应用程序的数学曲线. 曲线定义:起始点.终止点.控制点.通过调整控制点,贝塞尔曲线的形状会发生变化. 1962年,法国数学家Pierr ...
- 【shadow dom入UI】web components思想如何应用于实际项目
回顾 经过昨天的优化处理([前端优化之拆分CSS]前端三剑客的分分合合),我们在UI一块做了几个关键动作: ① CSS入UI ② CSS作为组件的一个节点而存在,并且会被“格式化”,即选择器带id前缀 ...
- AlloyRenderingEngine燃烧的进度条
写在前面 Github: https://github.com/AlloyTeam/AlloyGameEngine HTML 5新增了progress标签,那么再去使用AlloyRenderingEn ...