Java网络编程(四)—— ServerSocket(一)
- Java网络编程(四)—— ServerSocket(一)
- 总述
- 创建ServerSocket
- 绑定端口
- 使用ServerSocket
总述
之前《Java网络编程(三)—— Socket》介绍了客户端Socket。不过,只有客户端socket还不够,如果不能与服务器对话,客户端并没有什么用处,因此需要一个一直等待客户端连接的服务端。服务器就像坐在电话旁等电话的接线员。他们不知道谁会打电话,或者什么时间打电话,只知道当电话铃响时,就必须拿起电话与之对话,而不管对方是谁。
对于接受连接的服务器,Java提供了一个ServerSocket类表示服务器Socket。换句话说,服务器Socket的任务就是坐在电话旁等电话。从技术上讲,服务器Socket在服务器上运行,监听入站TCP连接。每个服务器Socket监听服务器机器上的一个特定端口。当远程主机上的一个客户端尝试连接这个端口时,服务器就被唤醒,协商建立客户端和服务器之间的连接,并返回一个常规的Socket对象,表示两台主机之间的Socket。换句话说,服务器Socket等待连接,而客户端Socket发起连接。一旦ServerSocket建立了连接,服务器会使用一个常规的Socket对象向客户端发送数据。数据总是通过常规socket传输。
创建ServerSocket
有4个公共的ServerSocket构造函数:
public ServerSocket(int port) throws BindException,IOException
public ServerSocket(int port, int queueLength) throws BindException,IOException
public ServerSocket(int port,int queueLength,InetAddress bindAddress) throws IOException
public ServerSocket() throws IOException
这些构造函数可以指定端口、保存入站连接请求所用的队列的长度,以及要绑定的本地网络接口。
绑定端口
使用无参构造函数会创建一个ServerSocket对象,但并没有将它具体绑定在某一个端口,所以初始时他没有接受任何连接,但是之后可以使用bind()来进行绑定,Java提供了两个函数来进行绑定:
public void bind(SocketAddress endpoint) throws IOException
public void bind(SocketAddress endpoint, int queuelength) throws IOException
使用这种方式,可以允许程序在绑定端口之前设置服务器socket选项,因为有些选项在服务器socket绑定之后就会被固定住:
ServerSocket ss = new ServerSocket();
/*
设置socket选项
*/
SocketAddress http = new InetSocketAddress(80);
ss.bind(http);
如果在InetSocketAddress中传入null,那么会选择任意端口。
使用ServerSocket
在Java中,服务器程序的生命周期是:
- 使用一个ServerSocket()构造函数在一个特定端口创建一个新的ServerSocket。
- ServerSocket使用其accept()方法监听这个端口的入站连接。accept()会一直阻塞,直到一个客户端尝试建立连接,此时accept()将返回一个连接客户端和服务器的Socket对象。
- 根据服务器的类型,会调用Socket的getInputStream()方法、getOutputStream()方法以获得与客户端通信的输入和输出流。
- 服务器和客户端根据已协商的协议交互,直到要关闭连接。
- 服务器或客户端(或二者)关闭连接。
- 服务器返回到步骤2,等待下一次连接。
下面这个简单的例子就是一个时间服务器,这个服务器的socket在6666端口进行监听,当有客户socket连接时,服务器就会返回时间。
public static void main(String[] args) throws Exception {
ServerSocket server = null;
try {
server = new ServerSocket(6666);
while (true) {
Socket connection = null;
try {
connection = server.accept();
Writer out = new OutputStreamWriter(connection.getOutputStream());
Date now = new Date();
out.write(now.toString() + "\r\n");
out.flush();
connection.close();
} catch (IOException ex) {
} finally {
try {
if (connection != null) connection.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}finally {
try {
if (server != null)
server.close();
} catch (IOException ex) {
}
}
}