java实现基于TCP协议网络socket编程(C/S通信)

一、前言:TCP原理简介

首先,保证文章完整性,TCP的理论原理还是需要简介一下,略显枯燥๑乛◡乛๑。

TCP(传输控制协议,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。TCP旨在适应支持多网络应用的分层协议层次结构。也就是说,TCP是为了在不可靠的互联网络上提供可靠的端到端字节流而专门设计的一个传输协议。 连接到不同但互连的计算机通信网络的主计算机中的成对进程之间依靠TCP提供可靠的通信服务。

以上TCP的特点,也正是与UDP的明显不同之处。UDP(用户数据报协议)是一种无连接的、不可靠的、不以字节流传输通信协议。具体区别可对比之前这篇文章:

【基于UDP协议网络Socket编程(java实现C/S通信案例) 】 [https://www.jb51.net/article/198498.htm]

接着,“三次握手”则是众所周知的一个词,是建立TCP连接的重要过程。许多文章有详细解读,本篇则是详细记录在此原理之上,使用Java实现TCP的Socket网络通信,包含C/S软件架构的程序设计,偏向实践,更加有趣!

二、Socket编程通信

本篇使用Java进行Socket编程,Java的TCP/IP套接字编程将底层的细节进行了封装,其编程模型如图:

我们自顶向下观察,基于TCP的通信,必然有服务端Server和客户端Client。

首先,建立连接。两端分别有一个套接字Socket,用于两者之间的通信。客户端向服务器发送请求,创建socket进行连接。服务端则随时监听客户端发起的请求,接收并创建裂解Socket。

其次,开始通信。服务和客户两端的输入输出流互相通信。逻辑上可理解为通信进程的双方具有两个流(输出流和输入流)。逻辑上可将两个流理解为两个通信管道的全双工通信模式,一个用于向对方发送数据,另一个用于接收对方的数据。

最后,结束通信。客户端访问服务器结束,断开连接,关闭Socket和相关资源(输入输出流等)。服务端监听客户端状态,同时关闭Socket等连接。

建立通信规则:

Server和Client之间需要约定相同的规则,保证正常通信。之后的程序设计,我们约定:

客户端连接服务器,连接成功后,服务器首先给客户端发送一条欢迎信息;

客户端程序每发送一条信息给服务器,服务器接收并回送该信息到客户端,客户端接收并显示该信息;

当客户端发送"bye",则结束对话。

三、TCP服务器端(具体代码)

第一步,创建服务端套接字。

类成员变量:ServerSocket serverSocket,监听端口号port;

  private int port =8008;//服务器监听窗口
  private ServerSocket serverSocket;//定义服务器套接字

  public TCPServer() throws IOException{
    serverSocket =new ServerSocket(port);
    System.out.println("服务器启动监听在"+port+"端口...");

  }

第二步,定义输入输出流方法:

 private PrintWriter getWriter(Socket socket) throws IOException{
    //获得输出流缓冲区的地址
    OutputStream socketOut=socket.getOutputStream();
    //网络流写出需要使用flush,这里在printWriter构造方法直接设置为自动flush
    return new PrintWriter(new OutputStreamWriter(socketOut,"utf-8"),true);
  }

  private BufferedReader getReader(Socket socket) throws IOException{
    //获得输入流缓冲区的地址
    InputStream socketIn=socket.getInputStream();
    return new BufferedReader(new InputStreamReader(socketIn,"utf-8"));
  }

第三步,服务端核心:

//单客户版本,每次只能与一个用户建立通信连接
public void Service(){
  while (true){
    Socket socket=null;
    try {
      //此处程序阻塞,监听并等待用户发起连接,有连接请求就生成一个套接字
      socket=serverSocket.accept();

      //本地服务器控制台显示客户连接的用户信息
      System.out.println("New connection accepted:"+socket.getInetAddress());
      BufferedReader br=getReader(socket);//字符串输入流
      PrintWriter pw=getWriter(socket);//字符串输出流
      pw.println("来自服务器消息:欢迎使用本服务!");

      String msg=null;
      //此处程序阻塞,每次从输入流中读入一行字符串
      while ((msg=br.readLine())!=null){
        //如果用户发送信息为”bye“,就结束通信
        if(msg.equals("bye")){
          pw.println("来自服务器消息:服务器断开连接,结束服务!");
          System.out.println("客户端离开。");
          break;
        }
        pw.println("来自服务器消息:"+msg);
      }
    }catch (IOException e){
      e.printStackTrace();
    }finally {
      try {
        if (socket!=null)
          socket.close();//关闭socket连接以及相关的输入输出流
      }catch (IOException e){
        e.printStackTrace();
      }
    }
  }
}

代码关键解析很清楚易懂。可以看到,服务端提供服务放到了一个While(true)里面,这是因为服务器程序需要一直运行,所以处理代码一般放在while(true)这种无限循环中,TCPServer运行一次,且自身不能终止运行,要终止它运行,只能通过强制方式(如在IDE环境强制关闭)。

四、TCP客户端(具体代码)

第一步,创建客户端套接字,定义类构造方法,实现输入输出流。

//单客户版本,每次只能与一个用户建立通信连接
public void Service(){
  while (true){
    Socket socket=null;
    try {
      //此处程序阻塞,监听并等待用户发起连接,有连接请求就生成一个套接字
      socket=serverSocket.accept();

      //本地服务器控制台显示客户连接的用户信息
      System.out.println("New connection accepted:"+socket.getInetAddress());
      BufferedReader br=getReader(socket);//字符串输入流
      PrintWriter pw=getWriter(socket);//字符串输出流
      pw.println("来自服务器消息:欢迎使用本服务!");

      String msg=null;
      //此处程序阻塞,每次从输入流中读入一行字符串
      while ((msg=br.readLine())!=null){
        //如果用户发送信息为”bye“,就结束通信
        if(msg.equals("bye")){
          pw.println("来自服务器消息:服务器断开连接,结束服务!");
          System.out.println("客户端离开。");
          break;
        }
        pw.println("来自服务器消息:"+msg);
      }
    }catch (IOException e){
      e.printStackTrace();
    }finally {
      try {
        if (socket!=null)
          socket.close();//关闭socket连接以及相关的输入输出流
      }catch (IOException e){
        e.printStackTrace();
      }
    }
  }
}

第二步,实现网络通信发送和接收方法。

  public void send(String msg){
    //输出字符流,由socket调用系统底层函数,经网卡发送字节流
    pw.println(msg);
  }

  public String receive(){
    String msg=null;
    try {
      //从网络输入字符流中读取信息,每次只能接受一行信息
      //不够一行时(无行结束符),该语句阻塞
      //直到条件满足,程序往下运行
      msg=br.readLine();
    }catch (IOException e){
      e.printStackTrace();
    }
    return msg;
  }

第三步,定义网络连接关闭方法供外部调用。

 public void close(){
    try {
      if (socket!=null)
        socket.close();
    }catch (IOException e){
      e.printStackTrace();
    }
  }

TCP连接的释放也有“四次握手”一说,必须经过2MSL后才真正释放。具体过程如下图:

五、通信效果演示

GIF动图演示:

六、“创意”机器人:价值一个亿的AI核心代码(具体代码)

这部分我们要实现“聊天机器人”,效果这样:

是不是迫不及待想知道如何实现呢!堪称“价值一个亿的AI核心代码”!!??

就这样实现了!

不卖关子了,就一行代码!

msg=msg.replace("?","!").replace("?","!").replace("吗","").replace("吗?","");

具体想实现机器人如何回复可以自行调整代码。

七、最后

本篇则是详细记录在此原理之上,使用Java实现TCP的Socket网络通信,包含C/S软件架构的程序设计,偏向实践,更加有趣!仔细阅读的朋友可以发现,在服务器端核心部分,有一行注释说明了该程序只支持单用户,也就是单线程通信,可以尝试一下,如果再开一个客户端连接该服务,是否因为单线程阻塞程序卡住了。

这个问题关键就在于:服务器和客户端互相约定通信规则,否则就可能有问题,例如,如果服务器在一个客户端连接成功后,并没有一条信息发送给客户端,客户端的读取欢迎信息的语句无法读取到内容,就被阻塞住,由于是单线程,甚至整个程序都会被卡住。要解决这个问题,等待更新下一篇!

另外,UI界面的设计可参考上一篇博客:【基于UDP协议网络Socket编程(java实现C/S通信案例) 】 [https://www.jb51.net/article/198498.htm]

到此这篇关于java实现基于TCP协议网络socket编程(C/S通信)的文章就介绍到这了,更多相关java TCP协议socket编程内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • JAVA实现基于Tcp协议的简单Socket通信实例

    好久没写博客了,前段时间忙于做项目,耽误了些时间,今天开始继续写起~ 今天来讲下关于Socket通信的简单应用,关于什么是Socket以及一些网络编程的基础,这里就不提了,只记录最简单易懂实用的东西.  1.首先先来看下基于TCP协议Socket服务端和客户端的通信模型: Socket通信步骤:(简单分为4步) 1.建立服务端ServerSocket和客户端Socket 2.打开连接到Socket的输出输入流 3.按照协议进行读写操作 4.关闭相对应的资源 2.相关联的API: 1.首先先来看下

  • Java编程实现基于TCP协议的Socket聊天室示例

    本文实例讲述了Java编程实现基于TCP协议的Socket聊天室.分享给大家供大家参考,具体如下: 这里使用Socket套接字进行编程,完成的是基于TCP可靠服务实现服务器与客户端的双通信. Server服务器端: package com.han; import java.awt.Container; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.Win

  • Java通过 Socket 实现 TCP服务端

    1 Java Socket简介 所谓socket 通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄.应用程序通常通过"套接字"向网络发出请求或者应答网络请求.Socket和ServerSocket类库位于Java.NET包中.ServerSocket用于服务器端,Socket是建立网络连接时使用的.在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话.对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或

  • Java Socket编程实例(三)- TCP服务端线程池

    一.服务端回传服务类: import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.util.logging.Level; import java.util.logging.Logger; public class EchoProtocol implements Runnable { private static f

  • Java实现Socket的TCP传输实例

    本文实例讲述了Java实现Socket的TCP传输.分享给大家供大家参考.具体分析如下: 客户端发数据到服务端 * Tcp传输,客户端建立的过程. * 1,创建tcp客户端socket服务.使用的是Socket对象. * 建议该对象一创建就明确目的地.要连接的主机. * 2,如果连接建立成功,说明数据传输通道已建立. * 该通道就是socket流 ,是底层建立好的. 既然是流,说明这里既有输入,又有输出. * 想要输入或者输出流对象,可以找Socket来获取. * 可以通过getOutputSt

  • Java基于Tcp协议的socket编程实例

    本文实例讲述了Java基于Tcp协议的socket编程方法,分享给大家供大家参考.具体分析如下: 以下是一对一的通信编程实现,后续会继续学习一个服务器监听多个客户端的实现. 这里用到的主要步骤如下: 第一步:以特定端口(如4800)新建socket对象 第二步:以系统输入设备构造BufferedReader对象,该对象用于接收系统键盘输入的字符 第三步:以socket对象 得到输出流来构造PrintWriter 第四步:以socket对象得到输入流来构造相应的BufferedReader对象,该

  • Java Socket编程实例(四)- NIO TCP实践

    一.回传协议接口和TCP方式实现: 1.接口: import java.nio.channels.SelectionKey; import java.io.IOException; public interface EchoProtocol { void handleAccept(SelectionKey key) throws IOException; void handleRead(SelectionKey key) throws IOException; void handleWrite(

  • Java Socket编程实例(一)- TCP基本使用

    一.服务端代码: import java.net.*; // for Socket, ServerSocket, and InetAddress import java.io.*; // for IOException and Input/OutputStream public class TCPEchoServer { private static final int BUFSIZE = 32; // Size of receive buffer public static void main

  • java实现一个简单TCPSocket聊天室功能分享

    本文实例为大家分享了java实现TCPSocket聊天室功能的相关代码,供大家参考,具体内容如下 1.TCPserver.java import java.net.*; import java.io.*; import java.util.*; import java.util.concurrent.*; public class TCPserver{ private static final int SERVERPORT = 8888; private ServerSocket MyServe

  • java实现基于Tcp的socket聊天程序

    对于步入编程行业不深的初学者或是已经有所领会的人来说,当学习一项新的技术的时候,非常渴望有一个附上注释完整的Demo.本人深有体会,网上的例子多到是很多,但是很杂不完整,写代码这种东西来不得半点马虎,要是错了一点,那也是运行不了的.这对于初学者来说更加的头疼,因为他根本不知道错在哪里,盲目的改只能错上加错.最后不得不去找找看看有没有能够直接运行的例子再加以模仿. 下面是博主在学习Java的socket时写的一个完整的例子,并且带上了完整的注释.它是一个简单的聊天程序,但是它可以设置任意多用户同时

随机推荐