网络协议
由于以太网最大的数据帧是1518Bytes,刨去以太网帧的帧头(DMAC目的MAC地址48bits=6Bytes+SMAC源MAC地址48bits=6Bytes+Type域2Bytes)14Bytes和帧尾CRC校验部分4Bytes,剩下承载上层协议的地方也就是Data域最大就只能有1500Bytes,这个值我们就把它称之为MTU。
UDP 包的大小就应该是 1500 - IP头(20) - UDP头(8) = 1472(Bytes)
TCP 包的大小就应该是 1500 - IP头(20) - TCP头(20) = 1460(Bytes)
UDP
- 面向无连接,速度较快,数据不可靠
- UDP 是用户数据报文协议的缩写,一个无连接的协议,提供了应用程序之间要发送的数据的数据包
TCP
- 三次握手,速度较慢,数据可靠
- TCP 是传输控制协议的缩写,它保障了两个应用程序之间的可靠通信,通常用于互联网协议,被称 TCP / IP
端口:一个端口只能同时被一个程序使用(有效范围 0 - 65535,动态范围 1024 - 65535)
IP地址对象
InetAddress
方法
具体见 Java API (~ ̄▽ ̄)~
static InetAddress[] getAllByName(String host)
static InetAddress getByAddress(byte[] addr)
static InetAddress getByAddress(String host,byte[] addr)
static InetAddress getByName(String host)
static InetAddress getLocalHost()
UDP实例
发送端
DatagramPacket packet = new DatagramPacket(buf, buf.length, address, port);// 构建发送数据包
DatagramSocket socket = new DatagramSocket(localPort);// 指定本地端口号(留空则随机端口号)
socket.send(packet);// 发送数据包
接收端
byte[] buf = new byte[1472];// UDP报文最大长度
DatagramPacket packet = new DatagramPacket(buf, buf.length);// 构建接收数据包
DatagramSocket socket = new DatagramSocket(localPort);// 指定本地端口号
socket.receive(packet);// 等待并接收数据包
byte[] returnBuf = new byte[packet.getLength()];// 构建返回的数据
System.arraycopy(buf, 0, returnBuf, 0, returnBuf.length);// 将收到的数据从缓冲区转移并返回
TCP实例
- 套接字使用TCP提供了两台计算机之间的通信机制。 客户端程序创建一个套接字,并尝试连接服务器的套接字。
- 当连接建立时,服务器会创建一个 Socket 对象。客户端和服务器现在可以通过对 Socket 对象的写入和读取来进行通信。
- java.net.Socket 类代表一个套接字,并且 java.net.ServerSocket 类为服务器程序提供了一种来监听客户端,并与他们建立连接的机制。
- 以下步骤在两台计算机之间使用套接字建立TCP连接时会出现:
- 服务器实例化一个 ServerSocket 对象,表示通过服务器上的端口通信。
- 服务器调用 ServerSocket 类的 accept() 方法,该方法将一直等待,直到客户端连接到服务器上给定的端口。
- 服务器正在等待时,一个客户端实例化一个 Socket 对象,指定服务器名称和端口号来请求连接。
- Socket 类的构造函数试图将客户端连接到指定的服务器和端口号。如果通信被建立,则在客户端创建一个 Socket 对象能够与服务器进行通信。
- 在服务器端,accept() 方法返回服务器上一个新的 socket 引用,该 socket 连接到客户端的 socket。
- 连接建立后,通过使用 I/O 流在进行通信,每一个socket都有一个输出流和一个输入流,客户端的输出流连接到服务器端的输入流,而客户端的输入流连接到服务器端的输出流。
- TCP 是一个双向的通信协议,因此数据可以通过两个数据流在同一时间发送.以下是一些类提供的一套完整的有用的方法来实现 socket
客户端
Socket socket = new Socket(remoteHostAddress, remoteHostPort);// 构建连接到远程主机的套接字
PrintWriter pout = new PrintWriter(socket.getOutputStream(), true);// 使用打印流, 开启自动刷新缓冲
BufferedReader pin = new BufferedReader(new InputStreamReader(socket.getInputStream()));// 使用缓冲读取流
BufferedReader keyboardInput = new BufferedReader(new InputStreamReader(System.in));// 读入键盘数据
String buffer;
while (true) {
if (! "quit".equals(buffer = keyboardInput.readLine())) {// 输入quit退出
pout.println(buffer);// 将键盘数据打印到服务端
if ((buffer = pin.readLine()) != null) {
System.out.println(buffer);// 打印服务端返回数据
}
}
}
服务端
ServerSocket serverSocket = new ServerSocket(localHostPort);// 建立服务端套接字
Socket socket = serverSocket.accept();// 得到套接字对象
BufferedReader bufIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));// 使用缓冲读取流(读到换行符为一行)
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);// 使用打印流
String line;
while ((line = bufIn.readLine()) != null) {
System.out.println(line);// 打印客户端发来的数据
out.println("Received:"+line);// 返回数据给客户端
}
网友评论