A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 夏一站 中级黑马   /  2013-6-12 19:38  /  1906 人查看  /  1 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

建立TCP客户端

客户端程序是一个daytime客户端,它连接到一个daytime服务器程序以读取当前的日期和时间。建立套接字连接并读取信息是一个相当简单的过程,只需要少量的代码。默认情况下daytime服务运行在13端口上。并非每台计算机都运行了daytime服务器程序,但是Unix服务器是客户端运行的很好的系统。如果你没有访问Unix服务器的权限。
DaytimeClient的代码 。

import java.net.*
import java.io.*;
public class DaytimeClient
{
public static final int SERVICE_PORT = 13;

public static void main(String args[])
{
// 检查主机名称参数
if (args.length != 1)
{
System.out.println ("Syntax - DaytimeClient host");
return;
}

// 获取服务器程序的主机名称
String hostname = args[0];

try
{
// 获取一个连接到daytime服务的套接字
Socket daytime = new Socket (hostname,
SERVICE_PORT);

System.out.println ("Connection established");

// 在服务器程序停止的情况下设置套接字选项
daytime.setSoTimeout ( 2000 );

// 从服务器程序读取信息
BufferedReader reader = new BufferedReader (
new InputStreamReader
(daytime.getInputStream()
));

System.out.println ("Results : " +
reader.readLine());

// 关闭连接
daytime.close();
}
catch (IOException ioe)
{
System.err.println ("Error " + ioe);
}
}
}

  1. try
  2. {
  3. // 绑定到80端口,提供TCP服务(类似与HTTP)
  4. ServerSocket myServer = new ServerSocket ( 80 );

  5. // ......
  6. }
  7. catch (IOException ioe)
  8. {
  9. System.err.println ("I/O error - " + ioe);
  10. }
复制代码
这是ServerSocket构造函数的最简单的形式,但是下面有一些其它的允许更多自定义的构造函数。所有这些函数都是公共的。· ServerSocket(int port)产生java.io.IOException、java.lang.SecurityException异常--把服务器套接字绑定到特定的端口号,这样远程客户端才能定位TCP服务。如果传递进来的值为零(zero),就使用任何空闲的端口--但是客户端可能没办法访问该服务,除非用什么方式通知了客户端端口号是多少。在默认情况下,队列的大小设置为50,但是也提供了备用的构造函数,它允许修改这个设置。如果端口已经被绑定了,或者安全性约束条件(例如安全性规则或知名端口上的操作系统约束条件)阻挡了访问,就会产生异常。

  · ServerSocket(int port, int numberOfClients)产生java.io.IOException、java.lang.SecurityException异常--把服务器套接字绑定到特定的端口号并为队列分配足够的空间用于支持特定数量的客户端套接字。它是ServerSocket(int port)构造函数的重载版本,如果端口已经被绑定了或安全性约束条件阻挡了访问,就产生异常。

  · ServerSocket(int port, int numberOfClients, InetAddress address)产生java.io.IOException、java.lang.SecurityException异常--把服务器套接字绑定到特定的端口号,为队列分配足够的空间以支持特定数量的客户端套接字。它是ServerSocket(int port, int numberOfClients)构造函数的重载版本,在多地址计算机上,它允许服务器套接字绑定到某个特定的IP地址。例如,某台计算机可能有两块网卡,或者使用虚拟IP地址把它配置成像几台计算机一样工作的时候。如果地址的值为空(null),服务器套接字将在所有的本地地址上接受请求。如果端口已经被绑定了或者安全性约束条件阻挡了访问,就产生异常。

  2、使用ServerSocket

  虽然Socket类几乎是通用的,并且有很多方法,但是Server Socket类没有太多的方法,除了接受请求并作为模拟客户端和服务器之间连接的Socket对象的产生组件就没有几个了。其中最重要的方法是accept()方法,它接受客户端连接请求,但是还有其它几个开发者可能感到有用的方法。

      方法
       如果没有注明的话该方法就是公共的。
  · Socket accept()产生java.io.IOException、java.lang.Security异常--等待客户端向某个服务器套接字请求连接,并接受连接。它是一种阻塞(blocking)I/O操作,并且不会返回,直到建立一个连接(除非设置了超时套接字选项)。当连接建立时,它将作为Socket对象被返回。当接受连接的时候,每个客户端请求都被默认的安全管理程序验证,这使得接受一定IP地址并阻塞其它IP地址、产生异常成为可能。但是,服务器程序不必依赖安全管理程序阻塞或终止连接--可以通过调用客户端套接字的getInetAddress()方法确定客户端的身份。

  · void close()产生java.io.IOException异常--关闭服务器套接字,取消TCP端口的绑定,允许其它的服务使用该端口。

  · InetAddress getInetAddress()--返回服务器套接字的地址,在多地址计算机中(例如某个计算机的本地主机可以通过两个或多个IP地址访问)它可能与本地地址不同。

  · int getLocalPort()--返回服务器套接字绑定到的端口号。

  · int getSoTimeout()产生java.io.IOException异常--返回超时套接字选项的值,该值决定accept()操作可以阻塞多少毫秒。如果返回的值为零,accept()操作无限期阻塞。

  · void implAccept(Socket socket)产生java.io.IOException异常--这个方法允许ServerSocket子类传递一个未连接的套接字子类,让这个套接字对象接受输入的请求。使用implAccept方法接受连接时,重载的ServerSocket.accept()方法可以返回已连接的套接字。很少开发者希望对ServerSocket再细分类,在不必要的情况下应该避免使用它。

  · static void setSocketFactory ( SocketImplFactory factory )产生java.io.IOException、java.net.SocketException、java.lang.SecurityException异常--为JVM指定服务器套接字产生组件。它是一个静态的方法,在JVM的生存周期中只能调用一次。如果禁止指定新的套接字产生组件,或者已经指定了一个,就会产生异常。

  · void setSoTimeout(int timeout)产生java.net.SocketException异常--为accept()操作指定一个超时值(以毫秒计算)。如果指定的值是零,超时设置就被禁止了,该操作将无限制阻塞。但是,如果允许超时设置,在accept()方法被调用的时候就启动一个计时器。当计时器期满时,产生java.io.InterruptedIOException异常,并允许服务器程序执行进一步的操作。

  3、从客户端接受和处理请求

  服务器套接字的最重要的功能是接受客户端套接字。一旦获取了某个客户端套接字,服务器就可以执行服务器程序的所有"真实的工作",包括从套接字读取信息、向套接字写入信息以实现某种网络协议。发送或接收的准确数据依赖于该协议的详细情况。例如,对存储的消息提供访问的邮件服务器将监听命令并发回消息内容。telnet服务器监听键盘输入并把这些信息传递给一个登陆外壳(shell),并把输出发回网络客户端。具体协议的操作与网络的相关性很小,更多的面向编程。

  下面的代码片断演示了如果接受客户端套接字,以及I/O流怎样连接到客户端:

// 执行阻塞的读取操作,读取下一个套接字
Socket nextSocket = someServerSocket.accept();

// 连接到流的过滤器读取和写入程序
BufferedReader reader = new BufferedReader (new
InputStreamReader
(nextSocket.getInputStream() ) );
PrintWriter writer = new PrintWriter( new
OutputStreamWriter
(nextSocket.getOutputStream() ) );

       从这个时候开始,服务器程序就可以处理任何需要完成的事务并响应客户端请求了,或者可以选择事务给另一个线程中的代码运行。请记住与Java中的其它形式的I/O操作类似,从客户端读取回应的时候代码会无限制阻塞--因此为了为多个客户端并行服务,必须使用多线程。但是在简单的情形中,多个执行线程可能是不必要的,特别是在对请求响应迅速并且处理时间很短的情况下。
建立完整实现通用Internet协议的客户端/服务器应用程序需要作大量的工作,对于网络编程的新手来说这一点更为明显。它也需要其它一些技巧,例如多线程编程。从现在开始,我们聚焦于一个简单的、作为单线程应用程序执行的TCP服务器程序框架。





评分

参与人数 1技术分 +1 收起 理由
曹睿翔 + 1 很给力!

查看全部评分

1 个回复

倒序浏览
您需要登录后才可以回帖 登录 | 加入黑马