十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
创新互联www.cdcxhl.cn八线动态BGP香港云服务器提供商,新人活动买多久送多久,划算不套路!
我们提供的服务有:网站建设、网站制作、微信公众号开发、网站优化、网站认证、徐州ssl等。为上千企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的徐州网站制作公司小编给大家分享一下用TCP协议实现客户端与服务器通信的方法,希望大家阅读完这篇文章后大所收获,下面让我们一起去探讨吧!
进行TCP协议网络程序的编写,关键在于ServerSocket套接字的熟练使用,TCP通信中所有的信息传输都是依托ServerSocket类的输入输出流进行的。
上一篇博客和大家分享了在网络编程中要注意的基础知识,关于IP、TCP、UDP以及端口和套接字的一些概念,想了解的小伙伴可以看我的这篇文章“盘点那些进行网络编程必须要知道的基础知识”,那么今天大灰狼就来和大家分享一下如何使用TCP/IP进行网络程序的开发。
TCP协议概念
先来了解一下TCP协议的基本概念。
我们知道TCP是可靠而非安全的网络协议。它可以保证数据在从一端送至另一端的时候可以准确的送达,并且抵达的数据的排列顺序和送出时的顺序是相同的。因此在进行TCP协议通信的时候,我们首先应该保证客户端和服务器之间的连接通畅。
而TCP协议程序的编写,仍然是依靠套接字Socket类来实现的,并且利用TCP协议进行通信的两个程序之间是有主次之分的,即一个是服务器的程序,另一个是客户端的程序。因此两者的功能和编写上也略有不同。如下图是服务器与客户端之间进行通信的示意图:
以上就是在TCP协议中客户端与服务器建立连接的过程示意图。而在这其中起到关键作用的就是服务器端套接字ServerSocket和客户端套接字Socket。通过这两个套接字来建立服务器和客户端,从而利用其中的函数进行数据的通信。
在ServerSocket类中有很多需要注意的地方,接下来大灰狼和大家分享一下ServerSocket类的具体用法:
ServerSocket类
ServerSocket类存在于Java.net包中,表示服务器端的套接字,在使用时需要首先导入这个类,我们也知道ServerSocket类的主要功能就是通过指定的端口等待来自于网络中客户端的请求并且进行连接。
值得注意的是:服务器套接字一次只能与一个客户端套接字进行连接,因此如果存在多台客户端同时发送连接请求,则服务器套接字就会将请求的客户端存放到队列中去,然后从中取出一个套接字与服务器建立的套接字进行连接,但是服务器端能够容纳的客户端套接字也不是无限的,当请求连接的数量大于大容纳量时,那么多出来的请求就会被拒接,一般来说队列的默认大小是50。
以下是ServerSocket类中一些常用的方法:
ServerSocket类中常用的方法
方法 | 返回值 | 说明 |
accept() | Socket | 等待客户机连接,若连接则创建一个客户端套接字 |
isBound() | boolean | 判断ServerSocket的绑定状态 |
getInetAddress() | InetAddress | 返回此服务器套接字的本地地址 |
isClosed() | boolean | 返回服务器套接字的关闭状态 |
close() | void | 关闭服务器套接字 |
bind(SocketAddress endpoint) | void | 将ServerSocket绑定到特定地址(IP地址和端口号) |
getInetAddress() | int | 返回服务器套接字等待的端口号 |
了解了ServerSocket类的基本方法之后,就是如何进行客户端和服务器进行连接的问题了。
在服务器端我们可以调用ServerSocket类的accpet()方法与请求连接的客户机建立连接,这时会返回一个和客户端相连接的Socket对象,这个时候其实已经连接成功了,使用getInetAddress()方法就可以获取到进行请求的客户机的IP地址。
对于如何进行客户端和服务器端数据的通信,就要用到数据的输入流和输出流了,服务器端的Socket对象使用getOutputStream()方法获取到的输出流,将指向客户端的Socket对象使用getInputStream()方法获取到的输入流。由此就实现在服务器向客户端发送数据的一个过程,同样的道理,客户端端的Socket对象使用getOutputStream()方法获取到的输出流,将指向服务器端的Socket对象使用getInputStream()方法获取到的输入流。从而实现由客户端向服务器发送数据的过程。
注意:accpet()方法会阻塞线程的继续执行,如果在对应的接口没有收到客户端的呼叫,则程序会停留在此处,直到获取到客户端的呼叫才会继续向下执行,但是如果服务器没有收到来自客户端的呼叫请求,并且accpet()方法没有发生阻塞,那么通常情况下就是程序出了问题,一般来说可能是使用了一个已经被其他程序占用了的端口号,导致ServerSocket没有绑定成功!遇到这种情况可以尝试更换新的端口号。
了解了TCP协议的通信过程,接下来就是进行TCP通信程序的书写啦!
在网络通信中,如果只要求客户机向服务器发送信息,不要求服务器向客户端反馈信息的行为称为“单向通信”,要求客户机和服务器双方互相通信的过程称为“双向通信”,双向通信只不过是比单向通信多了一个服务器向客户端发送消息的过程,
接下来分别是服务器端和客户端程序的编写:
服务器端程序
package server_1; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class MyTcp { private ServerSocket server; //设置服务器套接字 private Socket client; //设置客户端套接字 //连接客户端函数 void getServer() { try { server = new ServerSocket(1100); //建立服务器 端口为1100 System.out.println("服务器建立成功!正在等待连接......"); client = server.accept(); //调用服务器函数对客户端进行连接 System.out.println("客户端连接成功!ip为:" + client.getInetAddress()); //返回客户端IP getClientMessage(); //调用信息传输和接收函数 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } void getClientMessage() { try { while (true) { InputStream is = client.getInputStream(); //获取到客户端的输入流 byte[] b = new byte[1024]; //定义字节数组 int len = is.read(b); //由于信息的传输是以二进制的形式,所以要以二进制的形式进行数据的读取 String data = new String(b, 0,len); System.out.println("客户端发来消息:" + data); //定义发送给客户端的输出流 OutputStream put = client.getOutputStream(); String putText = "我已经收到!欢迎你!"; put.write(putText.getBytes()); //将输出流信息以二进制的形式进行写入 } } catch (Exception e) { // TODO: handle exception } try { //判断客户端字节流不是空,则关闭客户端 if (server != null) { server.close(); } } catch (Exception e) { // TODO: handle exception } } public static void main(String[] args) { // TODO Auto-generated method stub MyTcp myTcp = new MyTcp(); //调用该类生成对象 myTcp.getServer(); //调用方法 } }