读书笔记:

       socket连接应用算是java底层连接了,如果有对应的解决,应避免,如线程的底层条件锁和内部对象锁,应避免,可以使用阻塞队列也实现同步。

         Socket 感觉就是端口连接程序。

          已经有的scoket测试工具是telnet.

         

        SocketAddress 就是端口地址

                              |

  有个子类为:InetSocketAddress

         |                                 |

         |                                 |

 

分InetAddress                  端口

 

所以一个socket建立平时要InetSocketAddress,

它个构造方法有 Socket(String host, int port)

                       Socket(InetAddress address, int port)

也可以有先建立一个没有指定的,在事后指定,也有相关本地接口的。

 

获得一个连接 可以获得它的输入和输出流。

 

        输入流为读取,输出流为向服务器端写入数据。

 

ServerSocket为实现服务器端类。

若想可以连续的接受客户端的连接可以

while(true)
{
        socket=serverSocket.accept();
         new Thread(new Runnable(socket)).start();
}


为每一个来的客户端提供一个线程为它服务。

 

半关闭的socket

   socket.shutdownInput();
   socket.shutdownOutput();

 

当建立一个Socket程序时,可能阻塞,同理当套接字读取数据也肯能阻塞,这时 可先建一个空的套接字,在设置hostName 和port 加上超时时间参数。

对于读取的阻塞可有SocketChannel 来解决,

package v2chapter03.InterruptibleSocketTest;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import javax.swing.*;

/**
 * This program shows how to interrupt a socket channel.
 * @author Cay Horstmann
 * @version 1.01 2007-06-25
 */
public class InterruptibleSocketTest
{
   public static void main(String[] args)
   {
      EventQueue.invokeLater(new Runnable()
         {
            public void run()
            {
               JFrame frame = new InterruptibleSocketFrame();
               frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
               frame.setVisible(true);
            }
         });
   }
}

class InterruptibleSocketFrame extends JFrame
{
   public InterruptibleSocketFrame()
   {
      setSize(WIDTH, HEIGHT);
      setTitle("InterruptibleSocketTest");

      JPanel northPanel = new JPanel();
      add(northPanel, BorderLayout.NORTH);

      messages = new JTextArea();
      add(new JScrollPane(messages));

      interruptibleButton = new JButton("Interruptible");
      blockingButton = new JButton("Blocking");

      northPanel.add(interruptibleButton);
      northPanel.add(blockingButton);

      interruptibleButton.addActionListener(new ActionListener()
         {
            public void actionPerformed(ActionEvent event)
            {
               interruptibleButton.setEnabled(false);
               blockingButton.setEnabled(false);
               cancelButton.setEnabled(true);
               connectThread = new Thread(new Runnable()
                  {
                     public void run()
                     {
                        try
                        {
                           connectInterruptibly();
                        }
                        catch (IOException e)
                        {
                           messages.append("\nInterruptibleSocketTest.connectInterruptibly: " + e);
                        }
                     }
                  });
               connectThread.start();
            }
         });

      blockingButton.addActionListener(new ActionListener()
         {
            public void actionPerformed(ActionEvent event)
            {
               interruptibleButton.setEnabled(false);
               blockingButton.setEnabled(false);
               cancelButton.setEnabled(true);
               connectThread = new Thread(new Runnable()
                  {
                     public void run()
                     {
                        try
                        {
                           connectBlocking();
                        }
                        catch (IOException e)
                        {
                           messages.append("\nInterruptibleSocketTest.connectBlocking: " + e);
                        }
                     }
                  });
               connectThread.start();
            }
         });

      cancelButton = new JButton("Cancel");
      cancelButton.setEnabled(false);
      northPanel.add(cancelButton);
      cancelButton.addActionListener(new ActionListener()
         {
            public void actionPerformed(ActionEvent event)
            {
               connectThread.interrupt();
               cancelButton.setEnabled(false);
            }
         });
      server = new TestServer();
      new Thread(server).start();
   }

   /**
    * Connects to the test server, using interruptible I/O
    */
   public void connectInterruptibly() throws IOException
   {
      messages.append("Interruptible:\n");
      SocketChannel channel = SocketChannel.open(new InetSocketAddress("localhost", 8189));
      try
      {
         in = new Scanner(channel);
         while (!Thread.currentThread().isInterrupted())
         {
            messages.append("Reading ");
            if (in.hasNextLine())
            {
               String line = in.nextLine();
               messages.append(line);
               messages.append("\n");
            }
         }
      }
      finally
      {
         channel.close();
         EventQueue.invokeLater(new Runnable()
         {
            public void run()
            {
               messages.append("Channel closed\n");
               interruptibleButton.setEnabled(true);
               blockingButton.setEnabled(true);
            }
         });
      }
   }

   /**
    * Connects to the test server, using blocking I/O
    */
   public void connectBlocking() throws IOException
   {
      messages.append("Blocking:\n");
      Socket sock = new Socket("localhost", 8189);
      try
      {
         in = new Scanner(sock.getInputStream());
         while (!Thread.currentThread().isInterrupted())
         {
            messages.append("Reading ");
            if (in.hasNextLine())
            {
               String line = in.nextLine();
               messages.append(line);
               messages.append("\n");
            }
         }
      }
      finally
      {
         sock.close();
         EventQueue.invokeLater(new Runnable()
         {
            public void run()
            {
               messages.append("Socket closed\n");
               interruptibleButton.setEnabled(true);
               blockingButton.setEnabled(true);
            }
         });      
      }
   }

   /**
    * A multithreaded server that listens to port 8189 and sends numbers to the client, simulating a
    * hanging server after 10 numbers.
    */
   class TestServer implements Runnable
   {
      public void run()
      {
         try
         {
            ServerSocket s = new ServerSocket(8189);

            while (true)
            {
               Socket incoming = s.accept();
               Runnable r = new TestServerHandler(incoming);
               Thread t = new Thread(r);
               t.start();
            }
         }
         catch (IOException e)
         {
            messages.append("\nTestServer.run: " + e);
         }
      }
   }

   /**
    * This class handles the client input for one server socket connection.
    */
   class TestServerHandler implements Runnable
   {
      /**
       * Constructs a handler.
       * @param i the incoming socket
       */
      public TestServerHandler(Socket i)
      {
         incoming = i;
      }

      public void run()
      {
         try
         {
            OutputStream outStream = incoming.getOutputStream();
            PrintWriter out = new PrintWriter(outStream, true /* autoFlush */);
            while (counter < 100)
            {
               counter++;
               if (counter <= 10) out.println(counter);
               Thread.sleep(100);
            }
            incoming.close();
            messages.append("Closing server\n");
         }
         catch (Exception e)
         {
            messages.append("\nTestServerHandler.run: " + e);
         }
      }

      private Socket incoming;
      private int counter;
   }

   private Scanner in;
   private JButton interruptibleButton;
   private JButton blockingButton;
   private JButton cancelButton;
   private JTextArea messages;
   private TestServer server;
   private Thread connectThread;

   public static final int WIDTH = 300;
   public static final int HEIGHT = 300;
}

 

程序在前十个输出时,点击cancel按钮 都会使客户端阻塞,但是在10后有一段时间服务器是阻塞的,这时候只有SocketChannel 可以立即使客户端阻塞,客户端阻塞不影响,服务器端,服务器端依然会继续执行直到,结束。如果在服务器端:

 

if (counter <= 10) out.println(counter);
{
                System.out.println("休息中。。。");
               Thread.sleep(100);
}

可以发现服务器端一直会输出,如果100结束后,服务器端关闭,但是不点击cannel 那么客户端 不会阻塞,会一直输出reading.也就是说 客户端和服务器不是统一的,要是服务器端线程阻塞了,那么会阻塞客户端(如果是channel就不会影响),但是客户端阻塞不会影响服务器端,