转自:https://www.xuebuyuan.com/3215262.html

在Java中可以基于Socket,ServerSocket来实现TCP/IP+BIO的系统间通信。Socket主要用于实现建立连接及网络IO的操作,ServerSocket主要用于实现服务器端端口的监听及Socket对象的获取。

Socket实现客户端的关键代码如下:

/*创建连接,如果域名解析不了会抛出UnkownHostException,当连接不上时会抛出IOException。

       *如果希望控制建立连接的超时,可先调用socket=newSocket(),然后调用socket.connect(SocketAddress endpoint, int timeout) 方法

       */

       Socket socket = new Socket("www.baidu.com", 80);

       /* 将此选项设为非零的超时值时,在与此 Socket 关联的 InputStream 上调用 read() 将只阻塞此时间长度。

        * 如果超过超时值,将引发java.net.SocketTimeoutException,虽然 Socket 仍旧有效。

        * 选项必须在进入阻塞操作前被启用才能生效。

        * 超时值必须是 > 0 的数。超时值为 0 被解释为无穷大超时值。

        */

       socket.setSoTimeout(WAIT_TIME);//read操作时,5s后抛出SocketTimeoutException

       System.out.println("socketcreated!");

       try {

           //获取服务器端返回流

           InputStreamips = socket.getInputStream();

           BufferedReader bin=new BufferedReader(new InputStreamReader(ips));

           //创建向服务器写入流的PrintWriter

           System.out.println("inputstream getted:"+bin);

           PrintWriter out=new PrintWriter(socket.getOutputStream());

           //向服务器发送字符串信息,要注意的是,此次即使写入失败也不会抛出异常信息,

           //并且会一直阻塞到写入操作系统或网络IO出现异常为止。

           out.print("hello");

           //阻塞读取服务器端的返回信息,程序阻塞直到服务器端返回信息或网络IO出现

           //异常为止,如果希望在超过一段时间后就不再阻塞了,那么要在创建Socket对象

           //后调用socket.setSoTimeout(int timeout)

           try{

           String inputline=bin.readLine();

           }catch (SocketTimeoutException e) {

              System.out.println(e.getMessage()+";waitted time is:"+WAIT_TIME);

           }

       } finally {

           socket.close();

       }

       System.out.println("finished");

服务器端关键代码如下:

// 创建server 对本地指定端口的监听,如果端口冲突抛出SocketException,

       //其他网络IO异常抛出IOException

       ServerSocket s = new ServerSocket(LISTENING_PORT);

       //接受客户端建立连接的请求,并返回一个Socket对象,以便和客户端进行交互

       //交互的方式和客户端相同,通过getInputStream()和getOutputStream()

       //来进行读写。

       //此方法会一种阻塞直到有客户端发送建立连接的请求,如果希望限制阻塞时间,可以

       //通过调用setSoTimeout(int timeout)设置超时时间。超过指定时间后会抛出

       //s.setSoTimeout(WAIT_TIME);

       Socket incoming = s.accept();// 等待客户端连接

       if (incoming.isConnected()) {

           log.info("creat aconnect");

       }

上述代码中,基于Socket和Server能够建立简单的系统间通信。在实际的系统中,通常客户端同时要发送多个请求到服务器端,而服务器端同时要接受多个连接发送的请求。

为满足客户端能同时发送多个请求到服务器端,最简单的办法就是生成多个Socket。但这时就产生两个问题:

1.  生成太多的Socket会消耗过多的本地资源,在客户端机器多,服务器端机器少得情况下,客户端生成太多Socket会导致服务器要支撑非常大的连接数;

2. 生成Socket(建立连接)通常比较慢,因此频繁的创建会导致系统性能不足。

鉴于此,通常采用连接池的方式来维护Socket是比较好的,这样做,第一可以限制能创建的Socket的数目。第二由于将Socket放入连接池中,可以避免重复创建Socket带来的性能下降问题。比如数据库连接池就是典型例子。但是使用连接池同样有缺点,连接池中Socket数目有限,如果同时要用的Socket请求很多,就会造成激烈的竞争和等待。

此外,需要注意的一个问题是如何合理控制等待响应的超时时间,如果不设定超时会导致当服务器端出处理变慢时,客户端得相关请求都在做无限的等待,而客户端资源可能是有限的,才这种情况下很容易造成服务器端出现问题时,客户端挂掉。超时时间的具体设定,一般取决于客户端能承受的请求量及服务器端得处理时间。Java TCP/IP+BIO容易通过setSoTimeout方法设置阻塞等待时间。

为了满足服务器端能同时接受多个连接发送的请求,通常采用的方法是在accept获取Socket之后,将Socket放入一个线程中处理,通常将此方式描述为一个连接一线程。这样服务器可接受多个连接发送请求。这种方式存在的缺点是无论连接上是否有真实的请求,都要耗费一个线程。为避免创建过多的线程导致服务器端资源耗尽,必须限制创建线程的数量。因此采用BIO的情况下服务器端所能支持的并发连接数是有限的。

posted on 2020-04-15 03:05  Sharpest  阅读(200)  评论(0编辑  收藏  举报