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非常类似于电话插座.以一个国家级电话网 ...
随机推荐
- Effective前端4:尽可能地使用伪元素
伪元素是一个好东西,但是很多人都没怎么用,因为他们觉得伪元素太诡异了.其实使用伪元素有很多好处,最大的好处是它可以简化页面的html标签,同时用起来也很方便,善于使用伪元素可以让你的页面更加地简洁优雅 ...
- 使用roslyn代替MSBuild完成解决方案编译
原本我是使用批处理调用 MSBuild 完成解决方案编译的,新版的 MSBuild 在 Visual Studio 2015 会自带安装. 当然在Visual Studio 2015 中,MSBuil ...
- bzoj1878--离线+树状数组
这题在线做很麻烦,所以我们选择离线. 首先预处理出数组next[i]表示i这个位置的颜色下一次出现的位置. 然后对与每种颜色第一次出现的位置x,将a[x]++. 将每个询问按左端点排序,再从左往右扫, ...
- 工作中常用的git命令
一 常用Git命令 git clone:(区分SSH or HTTP) git init:初始化仓库 二 Git命令详解 Git Bash下,cd /c git clone,从远程Git版本库克隆一份 ...
- jvm内存区域
概述 jvm内存分为几个区域: 程序计数器 虚拟机栈 本地方法栈 堆 方法区 运行时常量池 直接内存 这些内存区域是在java进程中细分的,为java程序提供服务 不同的区域存储的内容不一样,生命周期 ...
- 【干货分享】前端面试知识点锦集01(HTML篇)——附答案
一.HTML部分 1.浏览器页面有哪三层构成,分别是什么,作用是什么? 构成:结构层.表示层.行为层分别是:HTML.CSS.JavaScript作用:HTML实现页面结构,CSS完成页面的表现与风格 ...
- 使用jquery.qrcode生成二维码(转)
jQuery 的 qrcode 插件就可以在浏览器端生成二维码图片. 这个插件的使用非常简单: 1.首先在页面中加入jquery库文件和qrcode插件. <script type=" ...
- JavaScript图表FusionCharts免费在线公开课,由印度原厂技术工程师主讲,10月13日发车
FusionCharts公开课达人还你做 轻松晋升图表大师 [开课时间]10月13日 14:30[主讲老师]印度原厂技术工程师[开课形式]网络在线公开课[活动费用]前50名免费 现在就可以报名哦 报 ...
- VS2012 Unit Test —— 我对IdleTest库动的大手术以及对Xml相关操作进行测试的方式
[1]我的IdleTest源码地址:http://idletest.codeplex.com/ [2]IdleTest改动说明:2013年10月份在保持原有功能的情况下对其动了较大的手术,首先将基本的 ...
- [Android]Android端ORM框架——RapidORM(v2.1)
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/6020412.html [Android]Android端ORM ...