目录html
1、前言:TCP原理简介java
5、通讯效果演示架构
6、“创意”机器人:价值一个亿的AI核心代码(具体代码)socket
7、最后函数
首先,保证文章完整性,TCP的理论原理仍是须要简介一下,略显枯燥๑乛◡乛๑。spa
TCP(传输控制协议,Transmission Control Protocol)是一种面向链接的、可靠的、基于字节流的传输层通讯协议。TCP旨在适应支持多网络应用的分层协议层次结构。也就是说,TCP是为了在不可靠的互联网络上提供可靠的端到端字节流而专门设计的一个传输协议。 链接到不一样但互连的计算机通讯网络的主计算机中的成对进程之间依靠TCP提供可靠的通讯服务。.net
以上TCP的特色,也正是与UDP的明显不一样之处。UDP(用户数据报协议)是一种无链接的、不可靠的、不以字节流传输通讯协议。具体区别可对比以前这篇文章:
【基于UDP协议网络Socket编程(java实现C/S通讯案例) 】 [https://www.cnblogs.com/chenzhenhong/p/13825286.html]
接着,“三次握手”则是众所周知的一个词,是创建TCP链接的重要过程。许多文章有详细解读,本篇则是详细记录在此原理之上,使用Java实现TCP的Socket网络通讯,包含C/S软件架构的程序设计,偏向实践,更加有趣!
本篇使用Java进行Socket编程,Java的TCP/IP套接字编程将底层的细节进行了封装,其编程模型如图:
咱们自顶向下观察,基于TCP的通讯,必然有服务端Server和客户端Client。
首先,创建链接。两端分别有一个套接字Socket,用于二者之间的通讯。客户端向服务器发送请求,建立socket进行链接。服务端则随时监听客户端发起的请求,接收并建立裂解Socket。
其次,开始通讯。服务和客户两端的输入输出流互相通讯。逻辑上可理解为通讯进程的双方具备两个流(输出流和输入流)。逻辑上可将两个流理解为两个通讯管道的全双工通讯模式,一个用于向对方发送数据,另外一个用于接收对方的数据。
最后,结束通讯。客户端访问服务器结束,断开链接,关闭Socket和相关资源(输入输出流等)。服务端监听客户端状态,同时关闭Socket等链接。
创建通讯规则:
Server和Client之间须要约定相同的规则,保证正常通讯。以后的程序设计,咱们约定:
客户端链接服务器,链接成功后,服务器首先给客户端发送一条欢迎信息;
客户端程序每发送一条信息给服务器,服务器接收并回送该信息到客户端,客户端接收并显示该信息;
当客户端发送"bye",则结束对话。
第一步,建立服务端套接字。
类成员变量: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环境强制关闭)。
第一步,建立客户端套接字,定义类构造方法,实现输入输出流。
private Socket socket; private PrintWriter pw; private BufferedReader br; public TCPClient(String ip, String port) throws IOException{ //主动向服务器发起链接,实现TCP三次握手 //不成功则抛出错误,由调用者处理错误 socket =new Socket(ip,Integer.parseInt(port)); //获得网络流输出字节流地址,并封装成网络输出字符流 OutputStream socketOut=socket.getOutputStream(); //参数true表示自动flush数据 pw=new PrintWriter(new OutputStreamWriter(socketOut,"utf-8"),true); //获得网络输入字节流地址,并封装成网络输入字符流 InputStream socketIn=socket.getInputStream(); br=new BufferedReader(new InputStreamReader(socketIn,"utf-8")); }
第二步,实现网络通讯发送和接收方法。
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核心代码”!!??
就这样实现了!
不卖关子了,就一行代码!
msg=msg.replace("?","!").replace("?","!").replace("吗","").replace("吗?","");
具体想实现机器人如何回复能够自行调整代码。
本篇则是详细记录在此原理之上,使用Java实现TCP的Socket网络通讯,包含C/S软件架构的程序设计,偏向实践,更加有趣!仔细阅读的朋友能够发现,在服务器端核心部分,有一行注释说明了该程序只支持单用户,也就是单线程通讯,能够尝试一下,若是再开一个客户端链接该服务,是否由于单线程阻塞程序卡住了。
这个问题关键就在于:服务器和客户端互相约定通讯规则,不然就可能有问题,例如,若是服务器在一个客户端链接成功后,并无一条信息发送给客户端,客户端的读取欢迎信息的语句没法读取到内容,就被阻塞住,因为是单线程,甚至整个程序都会被卡住。要解决这个问题,等待更新下一篇!
另外,UI界面的设计可参考上一篇博客:【基于UDP协议网络Socket编程(java实现C/S通讯案例) 】 [https://www.cnblogs.com/chenzhenhong/p/13825286.html]
个人博客园:https://www.cnblogs.com/chenzhenhong/p/13885290.html
个人CSDN博客:https://blog.csdn.net/Charzous/article/details/109260488