TCP通信
TCP协议:传输控制层协议,面向有链接,数据可靠
Socket
Socket通常也称作“套接字”,用于描述IP地址和端口,是一个通信链的句柄。在Internet上的主机一般运行了多个服务软件,同时提供集中服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。
应用程序通常通过“套接字”向网络发出请求或应答网络请求。Socket和Serversocket类库位于java.net包中。ServerSocket用于服务端,Socket是创建网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。
获取本地地址和端口号
java.net.Scoket为套接字类,其提供了很多方法,其中我们可以通过获取socket获取本地的地址以及端口号。
- 其方法为:
int getLocalPort();
用于获取本地使用的端口号InetAddress getLocalAddress();
用于获取套接字绑定的本地地址
使用InetAddress获取本地的地址方法:String getCanonicalHostName();
获取此IP地址的完全限定名String getHostAddress();
返回IP地址字符串(以文本表现形式) - 代码如下:
public static void main(String[] args) throws UnknownHostException, IOException {
Socket socket = new Socket("localhost",8088);
InetAddress add = socket.getLocalAddress();//获取本地信息
System.out.println(add.getCanonicalHostName());// 获取此IP地址的完全限定名
System.out.println(add.getHostAddress());//用于获取套接字绑定的本地地址
System.out.println(socket.getLocalPort());//用于获取本地使用的端口号
socket.close();
}
获取远程地址和端口号
Socket也提供了获取远端的地址以及端口号的方法:
- 其方法为:
int getPort();
用于获取远端使用的端口号InetAddress getInetAddress();
用于获取套接字绑定的远端地址 - 代码如下:
public static void main(String[] args) throws UnknownHostException, IOException {
Socket socket = new Socket("localhost",8088);
InetAddress inetadd = socket.getInetAddress();//获取远端信息
System.out.println(inetadd.getCanonicalHostName());// 获取此IP地址的完全限定名
System.out.println(inetadd.getHostAddress());//用于获取套接字绑定的远端地址
System.out.println(socket.getPort());//用于获取远端使用的端口号
socket.close();
}
获取网络输入/输出流
通过Socket获取输入流与输出流,这两个方法是使用Socket通讯的关键方法。封装了TCP协议的Socket是基于流进行通讯的,所以我们在创建了双方连接后,只需要获取相应的输入与输出流即可实现通讯。
- 其方法为:
InputStream getInputStream(); 该方法用于返回此套接字的输入流。
OutputStream getOutputStream(); 该方法用于返回此套接字的输出流 - 代码如下:
public static void main(String[] args) throws UnknownHostException, IOException {
Socket socket = new Socket("localhost",8088);
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
}
close方法
当使用Socket进行通讯完毕后,要关闭Socket以释放系统资源。
- 其方法为:
void close();
关闭Socket以释放资源
当关闭了该套接字后也会同时关闭由此获取的输入流与输出流。
Scoket通讯模块
Server端ServerSocket监听
java.net.ServerSocket是运行于服务端应用程序中,通过创建ServerSocket需要指定服务端口号,之后监听Socket的连接。
- 其方法为:
Socket accept();
该方法是一个阻塞方法,直到一个客户端通过Socket连接后,accept会封装一个Socket,该Socket封装的表示该客户端的有关信息,通过这个Socket与客户端进行通信。
- 代码如下:
//创建ServerSocket并申请服务端口8088
ServerSocket server = new ServerSocket(8088);
//方法会产生阻塞,知道某个Socket连接,并返回请求连接的Socket
Socket socket = server.accept();
Client端的Socket连接
当服务端ServerSocket调用accept方法阻塞等待客户端连接后,可以通过在客户端应用程序中创建Socket来向服务器发起连接。
{% note warning flat %}创建Socket的同时就发起连接,若连接异常会抛出异常,我们通常创建Socket时会传入服务端的地址及服务端口号。{% endnote %}
- 代码如下:
//参数1:服务端的IP地址,参数2:服务端的服务端口
Socket socket = new Socket("localhost",8088);
C-S端通信模块
C-S的全程为(Client-Server):客户端-服务器端
客户端与服务端通信模型如下:
- 步骤如下:
- 服务端ServerSocket
- 通过调用ServerSocket的accept方法监听客户端的连接
- 客户端创建Socket并指定服务端的地址以及端口来建立与服务端的连接
- 当服务端accept发现客户端连接后,后去对应该客户端的Socket
- 双方通过Socket分别获取对应的输入与输出流进行数据通讯
- 通讯结束后关闭连接5
Server端多线程模型
可以创建一个线程类,并将客户端交互的工作全部委托给线程处理,这样就可以实现当一个客户端连接后,启动一线程来负责与客户端的交互,这样我们就可以实现循环不断的监听其他客户端连接。
UDP通信
UDP协议:用户数据报协议,面向无连接,数据不可靠
DatagramPacket
创建接受包
DatagramPacket:UDP数据报给予IP建立,没太主机有65535个端口号可以使用。数据报中字结束限制为65535-8,包含8字节的头信息。
- 构造接受包:
DatagramPacket(byte[] buf, int length);
将数据报中Length长的数据装进Buf数组。DatagramPacket(byte[] buf, int offset, int lenth);
将数据报中从Offset开始、Length长的数据装进Buf数组。
创建发送包
- 构造发送包:
DatagramPacket(byte[] buf, int length, InetAddress clientAddress, int clientPort);
从buf数组中取出Length长的数据创建数据报对象,目标是clientAddress地址、clientPort端口,常用来发送数据给客户端。DatagramPacket(byte[] buf, int offset, int length, InetAddress clientAddress, int clientPort);
从buf数组中,取出offset开始、Length长的数据创建数据报对象,目标是clientAddress地址、clientPort端口,常用来发送数据给客户端。
DatagramSocket
服务端接受
DatagramSocket用于接受和发送UDP的Socket实例。
- 其语法格式为:
DatagramSocket(int port);
创建实例,并固定监听Port端口的报文。
- 其中方法:
receive (DatagramPacket d);
接受数据报文到d中,receive方法产生“阻塞”。会一直等待直到数据被读取到。
客户端发送
无参的构造方法DaragramSocket()通常用于客户端编程,它并没有特定监听的端口,仅仅使用一个临时的,程序会让操作系统分配一个可用的端口。
- 其中方法:
send (DatagramPacket dp);
该方法用于发送报文到目的地。
❤️ END ❤️