Logo

郎哥编程

构建TCP服务器

2020-01-10 169

在客户端和服务器端通信模式中,可以使用ServerSocket对象来构建TCP服务端。服务端需要创建监听特定端口的ServerSocket,ServerSocket负责接收客户连接请求,并生成与客户端连接的Socket。

ServerSocket类的构造方法说明如下:

ServerSocket()

该构造方法创建一个未绑定的服务器套接字。

ServerSocket(int port)

该构造方法创建绑定到指定端口的服务器套接字。参数port为指定的端口号。套接字的默认绑定IP地址为0.0.0.0,用来表示本机任意的ipv4地址。

ServerSocket(int port, int backlog)

该构造方法创建服务器套接字并将其绑定到具有指定backlog的指定本地端口号。参数port为端口号,参数backlog为请求传入连接队列的最大长度。如果连接请求在队列已满时到达,则连接将被拒绝。套接字的默认绑定IP地址为0.0.0.0,用来表示本机任意的ipv4地址。

ServerSocket(int port, int backlog, InetAddress bindAddr)

该构造方法使用指定的端口、侦听backlog和要绑定到的指定的IP地址创建服务器。参数bindAddr为指定IP地址的InetAddress对象。

ServerSocket类的常用方法说明如下:

Socket  accept()

该方法用于侦听与此套接字的连接请求,并接收该请求,该方法将阻塞,直到建立连接。该方法将返回一个新的套接字。

InetAddress    getInetAddress()

该方法返回此服务器套接字的本地地址。如果套接字在关闭前已绑定,则此方法将在套接字关闭后继续返回本地地址。

void   bind(SocketAddress endpoint)

该方法将服务器套接字绑定到特定地址(IP地址和端口号)。如果地址为空,那么系统将获取一个临时端口和一个有效的本地地址来绑定套接字。参数endpoint是SocketAddress类型,指定了要绑定的IP地址和端口号。

boolean    isBound()

该方法返回服务器套接字的绑定状态。

InetAddress     getInetAddress()

该方法返回此服务器套接字的本地地址。

int     getLocalPort()

该方法返回此套接字侦听的端口号。

void   close()

该方法关闭该套接字。关闭该套接字后,当前在accept()塞的任何线程都将抛出SocketException。

在服务器端创建ServerSocket对象,并绑定监听端口。调用ServerSocket对象的accept()方法监听客户端的请求。与客户端建立连接后,通过输入流读取客户端发送的请求信息,然后通过输出流向客户端发送响应信息,最后关闭socket及相关资源。

案例1:编写一个TCP服务端程序。建立TcpServer类,在TcpServer类中创建套接字,侦听指定的端口,等待连接请求。

在PCoreUnit11项目新建tcp包,在tcp包下新建TcpServer类。代码如下:

package tcp;
 
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
 
/**
 * @ClassName: TcpServer
 * @Description: 网络编程(构建TCP服务器)案例1
 * @author 编程训练营
 * @date
 *
 */
 
public class TcpServer {
    // 定义ServerSocket对象
    ServerSocket serverSocket = null;
   
    // 定义端口号
    int port;
 
    // 构造方法
    public TcpServer() {
       this.port = 9099;
    }
 
    /** 
    * @Title: getIp 
    * @Description: 获取服务器的IP地址 
    * @param @return    参数 
   
    * @return String    返回类型 
    * @throws 
    */ 
    public String getIp()
    {
       if( null != serverSocket )
       {
           InetAddress address  = serverSocket.getInetAddress();
           return address.getHostAddress();
       }
       return "";
    }
   
    /** 
    * @Title: init 
    * @Description: 初始化和启动服务器 
    * @param     参数 
   
    * @return void    返回类型 
    * @throws 
    */ 
    public void init() {
       System.out.println("服务器启动..."); 
       try {
           /**
            * 创建一个ServerSocket,这里可以指定连接请求的队列长度 new ServerSocket(port,3)
            * 意味着当队列中有3个连接请求时,如果客户端再请求连接,就会被服务器拒绝
            */
           serverSocket = new ServerSocket(port, 3);
           // 服务器循环监听连接请求
           while (true) {
              // 从请求队列中取出一个客户端的连接请求
              Socket client = serverSocket.accept();
              // 建立一个新线程处理这次连接
              new HandlerThread(client);
           }
       } catch (Exception e) {
           System.out.println("服务器异常: " + e.getMessage());
       }
    }
 
    /**
     * @ClassName: HandlerThread
     * @Description: 客户端请求线程处理类
     * @author 编程训练营
     * @date
     *
     */
    private class HandlerThread implements Runnable {
       // 定义socket
       Socket socket;
 
       // 构造方法
       public HandlerThread(Socket socket) {
           this.socket = socket;
           // 启动线程
           new Thread(this).start();
       }
 
       /**
        * <p>
        * Title: run
        * </p>
        * <p>
        * Description:
        * </p>
        *
        * @see java.lang.Runnable#run()
        */
 
       @Override
       public void run() {
           try {
              // 读取客户端数据
              BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
              // 这里要注意和客户端输出流的写方法对应,否则会抛 EOFException
              String clientInputStr = input.readLine();
              // 处理客户端数据
              System.out.println("客户端发过来的内容:" + clientInputStr);
 
              // 向客户端回复信息
              PrintStream out = new PrintStream(socket.getOutputStream());
              System.out.print("请输入:\t");
              // 发送键盘输入的一行
              String s = new BufferedReader(new InputStreamReader(System.in)).readLine();
              out.println(s);
 
              out.close();
              input.close();
           } catch (Exception e) {
              System.out.println("服务器 run 异常: " + e.getMessage());
           } finally {
              if (socket != null) {
                  try {
                     socket.close();
                  } catch (Exception e) {
                     socket = null;
                     System.out.println("服务端 finally 异常:" + e.getMessage());
                  }
              }
           }
 
       }
 
    }
 
}

编写TCP服务端程序的主要步骤如下:

(1)   实例化ServerSocket对象,创建套接字;

(2)   调用ServerSocket对象的accept()方法监听端口;

(3)   accept()方法监听到连接请求后,会返回Socket对象,accept()是堵塞方法,如果没有客户端的连接请求,方法后面的代码不会执行;

(4)   建立一个新的线程,利用I/O流与客户端进行通信,

(5)   通信完成后,关闭Socket。

在tcp包下新建TcpServerTest测试类,启动服务器。代码如下:

package tcp;
 
/** 
* @ClassName: TcpServerTest 
* @Description: 网络编程(构建TCP服务器)案例1
* @author 编程训练营 
* @date 
* 
*/
 
public class TcpServerTest {
 
    /** 
    * @Title: main 
    * @Description: Java程序入口main方法  
    * @param @param args    参数 
   
    * @return void    返回类型 
    * @throws 
    */
 
    public static void main(String[] args) {
       // 实例化TcpServer对象
       TcpServer tcpserver = new TcpServer();
       // 启动服务
       tcpserver.init();
      
    }
 
}

程序TcpServerTest实例化TcpServer对象,并调用TcpServer对象的init()方法启动服务器。

代码在线纠错(通义千问 qwen-max)

支持粘贴多个代码文件,提交后由阿里云通义千问自动分析代码漏洞、语法错误、逻辑问题并给出修改建议。
您已解锁 AI 代码纠错功能,可正常使用!

评论区

登录 后发表评论
暂无评论