java网络编程(下)

来源:互联网 发布:java微服务是什么 编辑:程序博客网 时间:2024/06/06 05:19

一、客户端Socket

  • 定义:Socket是两台主机之间的一个连接,一单建立了连接,本地和远程主机就从这个socket得到输入流和输出流,使用这个流可以同时发送和接收数据。Socket对程序员掩盖了网络的底层细节,如错误检测、包大小、包分解、包重传、网络地址等。

1.构造和连接 Socket

  • javanetSocket 类是java完成客户端 TCP 操作的基础类,这个类使用原生代码与主机操作系统的本地 TCP 栈进行通信。
  • 构造函数:

    1. pubic Socket(String host,int port) throws UnknownHostException,IOException
    2. public Socket(InetAddress host,int port) throws IOException
    3. /**
    4. 下面两个构造函数可以指定本地网络接口和端口来连接,网络接口可以是物理接口也可以是虚拟接口,如果localPort传入 0,java则会随机选择 1024 到 65535 之间的一个可用端口
    5. */
    6. public Socket(String host,int port,InetAddress interface,int localPort) throws IOException,UnknownHostException
    7. public Socket(InetAddress host,int port,InetAddress interface,int localPort) throws IOException
    8. //看源码其实可以发现传入的参数其实是两个 SocketAddress(Address + port),一个是连接的主机,一个是本地网络接口。
    9. /**
    10. 以上的所有的构造方法中都会调用另外一个构造函数:
    11. public Socket (SocketAddress address,SocketAddress localAddr,boolean stream):在这个构造函数中会调用 bind(localAddress);connect(address);所以建立连接时是要先创建一个 Socket,然后调用 bind 方法开始绑定,最后调用 connect 方法进行连接。
    12. 所以以下3个构造函数是没有进行连接的
    13. */
    14. public Socket()
    15. public Socket(Proxy proxy)
    16. protected Socket(SocketImpl impl)
    • 当建立起了连接,这时候就可以开始相互发送数据了。

      1. public InputStream getInputStream() throws IOException//获得输入流,可以从中获取服务端发来的数据
      2. public OutputStream getOutputStream() throws IOException;//获得输出流,可以用其向服务端发送数据
    • 半关闭 Socket

      1. public void close();//同时关闭 Socket的输入和输出流
      2. public void shutdownInput() throws IOException ;//关闭输入流,shutdown方法并不关闭socket
      3. public void shutdownOutput() throws IOException ;//关闭输出流,
    • 获取 Socket的信息

      1. public InetAddress getInetAddress();//返回远程主机的地址
      2. public int getPort();//返回远程主机的端口
      3. public InetAddress getLocalAddress();//返回本地主机的地址
      4. public int getLocalPort();//返回本地主机的端口
      5. public boolean isClosed();//是否已经关闭
      6. public boolean isConnected();//表示的是:是否从未连接过一个远程主机,只要连接过,就返回true
    • Socket选项:都有对应的getter 与 setter 方法

      1. TCP_NODELAY:是否关闭 Socket 的缓冲,如果关闭了,则一旦就绪就会发送,而不会等到缓冲区满
      2. SO_LINGER:表示当socket关闭时如何处理尚未发送的数据报,可以设置延迟的秒数,一旦时间到,无论还有没有数据都关闭连接。最大延迟时间为65535
      3. SO_TIMEOUT:表示从socket获取数据时,read方法会阻塞的时长。0为无限,也是默认值
      4. SO_REVBUF:设置接收缓冲区的大小,头层皮利用缓冲区提升网络的性能
      5. SO_SNDBUF:设置发送缓冲区的大小,但是实际上会设置为发送 接收缓冲区大小较小的一个
      6. SO_KEEPALIVE:客户端会偶尔通过一个空闲连接发送一个数据包,以确保服务器未崩溃
      7. OOBINLINE:Out Of Band ,紧急数据,会立即发送
      8. SO_REUSEADDR:重用端口,可能会出现前一个Socket 未接收的数据

2.Socket地址

  • 定义:SocketAddress类表示一个连接端点,这是个空的抽象类,其主要用途是为暂时的 Socket连接信息(如 ip地址 和 端口)提供一个方便的存储
  • 方法:

    1. public SocketAddress getRemoteSocketAddress();//返回的是所连接系统的地址
    2. public SocketAddress getLocalSocketAddress();//返回的是发起连接的地址
  • 子类 InetSocketAddress

    • 创建: 
      1. public InetSocketAddressInetAddress addressint port
      2. public InetSocketAddressStringint port
      3. public InetSocketAddressint port
      4. //静态构造方法
      5. public static InetSocketAddress createUnresolved(String host,int port)//不会在DNS 中查找主机
      6. //获取方法
      7. public final InetAddress getAddress()
      8. public final int getPort()
      9. public final String getHostName()

    二、服务器 Socket

    • 服务器就像是坐在电话胖等电话的接线员,它不管对方是谁。只管监听入站的TCP连接

    1.创建

    1. //监听 端口为 port的入站连接
    2. public ServerSocketint port throws BindExceptionIOException
    3. //queue 代表的是在队列中未处理连接的最大容量,当达到最大值是,主机会拒绝这个端口上的额外连接,知道队列腾出新的位置为止,客户端在首次连接被拒绝后还会尝试建立连接
    4. public ServerSocketint portint queueLength throws BindExceptionIOException
    5. //InetAddress 绑定一个特定的本地 ip地址,服务器就值监听这个指定地上上的入站连接。因为一个主机有多个网络接口或ip地址,服务器在默认情况下会监听所有的接口和ip地址的指定端口上监听
    6. public Serversocketint portint queueLengthInetAddress bindAddress throws IOException
    7. //创建一个ServerSocket对象,旦没有绑定到某个端口。需要调用 bind(socketAddress)来进行绑定
    8. public ServerSocket() throws IOException

    2.方法

    • 当获取到的 ServerSocket对象过后,可以通过 accept方法获取一个 Socket对象(accept方法会监听指定端口的入站连接,一直阻塞到有客户端尝试建立连接),然后对socket进行操作,可以对其进行数据传输
    • 关闭serverSocket:close()方法。关闭 serverSocket 会释放本地主机的一个端口,允许另一个服务器绑定到这个端口,还会中断该serversocket已经接受的目前处于打开状态的所有socket。当关闭了一个serversocket之后,就不能在重新连接
    • isBound():判断一个serverSocket是否曾打开过
    • public InetAddress getInetAddress():返回服务器(本地主机)使用的地址,如果还没绑定,则返回null
    • public int getLocalPort():返回端口号,如果没有绑定到某个端口,则返回 -1.如果绑定到所有接口,则

    3.服务Socket选项:有对应的getter 与 setter 方法

    1. SO_TIMEOUT:等待入站连接的时间,如果到时了,就会跑出异常
    2. SO_REUSEADDR:是否允许一个新的Socket绑定到之前使用过的一个端口,肯呢个会存在之前Socket的数据
    3. SO_RCVBUF:设置服务器 Socket接收客户端默认接收缓存区大小

    三、测试代码

    • 说明:因为socket中的流是阻塞式的,会一直等待数据。所以要双方定义结束协议:这里的协议为 “#标志着结束”

    1.服务端 Server.java

    1. public class Server {
    2. public static void main(String[] args) {
    3. ServerSocket server = null;
    4. Socket socket = null;
    5. try {
    6. server = new ServerSocket(1335);
    7. if (server.isBound()) {
    8. System.out.println("server is open");
    9. }
    10. socket = server.accept();
    11. InputStream in = socket.getInputStream();
    12. StringBuffer buffer = new StringBuffer("");
    13. int b = 0;
    14. while (true) {
    15. if ((b = in.read()) == '#') break;
    16. buffer.append((char)b);
    17. }
    18. System.out.println("Server receive data from client:" + buffer.toString());
    19. System.out.println("server send data to client...");
    20. OutputStream out = socket.getOutputStream();
    21. out.write("hello,client#".getBytes());
    22. } catch (Exception e) {
    23. e.printStackTrace();
    24. } finally {
    25. if (socket != null) {
    26. try {
    27. socket.close(); //it close stream as well
    28. } catch (IOException e) {
    29. e.printStackTrace();
    30. }
    31. }
    32. }
    33. }
    34. }

    2.客户端 Client.java

    1. public class Client {
    2. public static void main(String[] args){
    3. Socket socket = null;
    4. try {
    5. socket = new Socket("172.22.113.134",1335);
    6. if (socket.isConnected()){
    7. System.out.println("client is create");
    8. }
    9. System.out.println("client send data to server");
    10. OutputStream out = socket.getOutputStream();
    11. out.write("hello,server,i'm client#".getBytes());
    12. InputStream in = socket.getInputStream();
    13. StringBuffer buffer = new StringBuffer("");
    14. int c = 0;
    15. while (true) {
    16. if ((c = in.read()) == '#') break;
    17. buffer.append((char)c);
    18. }
    19. System.out.println("client receive data form server:" + buffer.toString());
    20. }catch (Exception e){
    21. e.printStackTrace();
    22. }finally {
    23. if (socket != null){
    24. try {
    25. socket.close();
    26. }catch (Exception e){
    27. e.printStackTrace();
    28. }
    29. }
    30. }
    31. }
    32. }

    3.运行结果

    • 对于Server.java

      1. server is open
      2. Server receive data from client:hello,server,i'm client
      3. server send data to client...
    • 对于Client.java

      1. client is create
      2. client send data to server
      3. client receive data form server:hello,client
+
 2016-07-24 09:18 字数 5269 阅读 0

0 0
原创粉丝点击