美文网首页
Java-TCP编程(一)

Java-TCP编程(一)

作者: alexwu59 | 来源:发表于2019-06-10 15:59 被阅读0次

Java提供的TCP编程,分为客户端和服务器两种不同的API,下面首先介绍服务器API

服务器

在java中TCP连接的服务器方式是通过ServerSocket类实现,ServerSocket类有多个构造函数:

//创建一个没有绑定端口和地址的服务端 socket
public ServerSocket();
//创建一个服务端 socket并且执行bind()方法绑定到指定的port端口上
public ServerSocket(int port);
//创建一个服务端socket并且执行bind()方法绑定到指定的port端口上,并且设置客户端请求队列大小
//backlog参数设置客户端连接的请求数
public ServerSocket(int port, int backlog) 
//创建一个服务端socket并且执行bind方法绑定到指定的bindAddr地址上
public ServerSocket(int port, int backlog, InetAddress bindAddr) 

一般情况应该使用不带参数的构造方法创建ServerSocket对象,因为这种方式可以在执行bind方法之前进行参数配置。服务器端可以设置的参数配置包括如下:

//是否复用未完全关闭的地址端口,比如可以使用tcp连接处于TIME_WAIT状态或者 2MSL状态的端口
serverSocket.setReuseAddress(true);
//该值有两层含义 1.设置每一个与客户端建立连接的socket内部缓存大小
//                          2.向远程主机公布自己设置的TCP协议的接受窗口大小
//该值可以在accept方法之后进行设置,但是如果设置的值大小超过了64k,
//那么必须在执行bind方法之前设置该值。因此必须采用无参构造函数
//创建ServerSocket对象,并且在绑定地址之前调用setReceiveBufferSize方法设置该值;
serverSocket.setReceiveBufferSize(1024);
//设置调用accept方法的阻塞时间,如果阻塞时间超过了设定值,那么会抛出SocketTimeoutException
//异常,如果不设置或者设置为0表示一直会阻塞
serverSocket.setSoTimeout(100);
//设置tcp连接的性能偏好策略,这三个参数分别代表不同的属性,具体值是相对于属性的权重
//三个参数分别表示: 用最少时间建立连接   延迟  带宽
serverSocket.setPerformancePreferences(1,1,1);

设置完相关参数之后,执行绑定操作,把serversocket绑定的本地的某个ip地址和端口上,并且设置可接受的客户端最大请求数

serverSocket.bind(new InetSocketAddress("localhost",8000),50);

绑定结束之后,调用accept方法,开始监听客户端发来的tcp连接请求:

Socket socket =   serverSocket.accept();

当调用accept方法后,服务端进入阻塞状态,直到有客户端请求过来或者SoTimeout时间到达。当客户端有tcp连接请求过来,该方法会返回Socket对象用于处理服务器和客户段之前的网络通信。
全部代码如下:

public class TCPServer {
    public static void main(String[] args) throws Exception {

        try(ServerSocket serverSocket = new ServerSocket()){
            serverSocket.setReuseAddress(true)      
            serverSocket.setReceiveBufferSize(1024);
            serverSocket.setSoTimeout(0);
            serverSocket.setPerformancePreferences(1,1,0);
            serverSocket.bind(new InetSocketAddress("localhost",8000),50);
            Socket socket =   serverSocket.accept();
            InputStream read = socket.getInputStream();
            byte[] data = new byte[1024];
            int count = read.read(data);
            String clientData = new String(data,0,count,"utf-8");
            System.out.println("client:"+clientData);
            OutputStream write = socket.getOutputStream();
            data = "I'm tcp server !".getBytes();
            write.write(data);
            read.close();
            write.close();
            socket.close();
        }
    }
}

客户端

下面介绍客户端API使用,客户端使用Socket类,Socket类也有多个实现方法:

public Socket();
//通过代理访问远程服务器
public Socket(Proxy proxy) 
//创建并连接访问host和port的服务器主机的socket
public Socket(String host, int port)
//以InetAddress的方式创建客户端的socket
public Socket(InetAddress address, int port)
//创建访问远程主机host,并且绑定到本地IP localAddr和本地端口localPort
public Socket(String host, int port, InetAddress localAddr,  int localPort) 
//以InetAddress方式绑定远程主机和本地ip地址
public Socket(InetAddress address, int port, InetAddress localAddr,int localPort)

以上构造方法,除了无参构造方法,其他构造方法,在创建Socket对象的同时,会发起于服务段的TCP连接,通常会在发起服务器连接之前,进行相关参数设置,因此,通常我们使用无惨构造方法,创建Socket对象之后,再调用bind方法绑定到客户端本地的ip和本地端口。

 socket.bind(new InetSocketAddress("localhost",8888));

下面进行socket的参数进行设置:

 //设置阻塞时间,TCP中的阻塞时间包括: ServerSocket.accept()  SocketInputStream.read()
            //serverSocket设置的是accept的阻塞时间,socket设置的是read的阻塞时间
            socket.setSoTimeout(100);
            //是否复用未完全关闭的地址端口,比如可以使用tcp连接处于TIME_WAIT状态或者 2MSL状态的端口
            socket.setReuseAddress(true);
            //是否启用Nagle's算法
            socket.setTcpNoDelay(true);
            //如果该值设置为true,当TCP双方2个小时(取决于具体实现)内没有数据交互的时候,TCP自动发送keepalive探测
            //该探测回有三种返回:1.正常返回ACK报文,表示服务正常 2.返回RST报文,表示服务已经宕机重启 3.没有返回结果
            //表示服务已经宕机,socket已经关闭
            socket.setKeepAlive(true);
            //启用并设置延迟关闭socket连接,该值通常可以设置三种取值:
            //false,any: 当设置为false的时候,socket在执行close的时候,会立即关闭。底层系统接管输出流,负责把数据发送出去
            //true,2000: socket会在关闭之前等到数据发送完成。如果时间超过了2000毫秒,缓冲区数据还没发送完成,
            //          那么socket会立即关闭,缓冲区数据被丢弃,然后发送RST报文
            //true,0: 那么socket会立即关闭,缓冲区数据被丢弃,然后发送RST报文
            socket.setSoLinger(true,1000);
            //设置是否启用紧急数据 通常不启用
            socket.setOOBInline(false);
            //设置接受缓存大小
            socket.setReceiveBufferSize(1024);
            //设置发送缓存大小
            socket.setSendBufferSize(1024);
            //设置TCP连接的策略
            socket.setPerformancePreferences(1,0,1);

设置完参数之后,就可以调用connect方法连接服务器了:

//这里的localhost是远程主机的名称,9999是远程主机的端口号
socket.connect(new InetSocketAddress("localhost",9999));

下面的是全部客户端的代码:

public class TCPClient {

    public static void main(String[] args) throws Exception{

        try(Socket socket = new Socket()){
            socket.bind(new InetSocketAddress("localhost",8888));
            socket.setSoTimeout(100);
            socket.setReuseAddress(true);
            socket.setTcpNoDelay(true);
            socket.setKeepAlive(true);
            socket.setSoLinger(true,1000);
            socket.setOOBInline(false);
            socket.setReceiveBufferSize(1024);
            socket.setSendBufferSize(1024);
            socket.setPerformancePreferences(1,0,1);

            socket.connect(new InetSocketAddress("localhost",9999));
            OutputStream out = socket.getOutputStream();
            out.write("I'm client".getBytes());
            InputStream read = socket.getInputStream();
            byte[] data = new byte[1024];
            int count = read.read(data);
            String serverData = new String(data,0,count,"utf-8");
            System.out.println("Tcp Client:"+serverData);
            out.close();
            read.close();
        }
    }
}

相关文章

  • Java-TCP编程(一)

    Java提供的TCP编程,分为客户端和服务器两种不同的API,下面首先介绍服务器API 服务器 在java中TCP...

  • Rxjava总结

    概念 函数式编程就是一种编程范式,常见的编程范式有命令式编程 函数式编程 和逻辑式编程。。。常见的面向对象编程是一...

  • RxJava系列|RxJava简介(一)

    函数响应式编程 函数式编程是一种编程范式。 常见的编程范式有:命令式编程、函数式编程和逻辑式编程。 面向对象就是一...

  • 探秘Spring AOP

    编程范式概览 面向过程编程 面向对象编程 函数式编程 事件驱动编程 面向切面编程 AOP是什么 是一种编程范式,不...

  • AOP

    一、概述 编程范式概述 面向过程编程 面向对象编程 面向切面编程 函数式编程 事件驱动编程(GUI) 主要解决问题...

  • 函数式编程-前置知识(1)

    什么是函数式编程 函数式编程是编程范式之一,我们常听说的编程范式还有面向过程编程,面向对象编程。 面向对象编程的思...

  • RxJava2

    函数式编程是一种编程范式。我们常见的编程范式有命令式编程、函数式编程和逻辑式编程。我们常见的面向对象编程是一种命令...

  • 函数式编程

    函数式编程(FP) 一种编程范式, 类似于面向对象编程和面向过程编程。 一 基本的函数式编程 基本的函数式编程 纯...

  • swift注意事项

    一、编程范式 Swift 可以面向协议编程(POP)、函数式编程、面向对象编程。 Object-C 以面向对象编程...

  • 你真的理解面向对象吗?

    面向对象 我们常见的编程范式有命令式编程,函数式编程,逻辑式编程,而面向对象编程是一种命令式编程。 命令式编程是面...

网友评论

      本文标题:Java-TCP编程(一)

      本文链接:https://www.haomeiwen.com/subject/hlpmxctx.html