1. 计算机网络结构
五层模型
层 | 该层的协议 |
---|
应用层 | HTTP、FTP、SMTP… | 传输层 | TCP、UDP… | 网络层 | IP、ICMP… | 链路层 | FDDI、PPP… | 物理层 | IEEE… |
各层次协议的数据单元
- 应用层:报文(message)
- 传输层:报文段(segment):TCP段,UDP数据报
- 网络层:分组packet(如果无连接方式:数据报datagram)
- 数据链路层:帧(frame)
- 物理层:位(bit)
两个端点通信的过程
图片来源 中科大郑烇、杨坚全套《计算机网络》
2. Socket 概念
Socket是两个主机间会话关系的标识(通过ip、port实现)。
Socket位于应用层和传输层之间,是传输层提供给应用层的服务,实现形式是Socket API。
在程序中Socket就是一个int 数(指向某一个会话,相当于句柄),这样是为了减少层间传输的信息量(不用每次要传本机ip、本机port、目标ip、目标port),简单,便于管理。
例:1001,1002表示了两个会话
Scoket数 | 本机ip | 本机port | 目标ip | 目标port |
---|
1001 | 1.1.1.1 | 8888 | 2.2.2.2 | 80 | 1002 | 1.1.1.1 | 8888 | 2.2.2.2 | 433 |
注:表中的两个会话虽然使用了同一个本地端口,但是能通过socket区分,所以可以同时进行通信。
TCP Socket
TCP Socket基于传输层的TCP协议,是一个四元组,包含本机ip、本机port、目标ip、目标port。 在基于TCP时,应用层向传输层传输时要提供 TCP Socekt 和 报文 两部分。在传输层被封装为报文段,网络层会通过TCP Socekt 提取目标ip+port进行寻址。
UDP Socket
UDP Socket基于传输层的UDP协议,是个二元组,包含本机ip、本机port。 在基于UDP时,应用层向传输层传输时要提供 UDP Socekt 、报文和目标ip+目标port 三部分。UDO Socekt和报文会被封装为数据报,目标ip+port则会通过传输层交给网络层进行寻址。
3. Java代码实现Socket通信
3.1 TCP通信
服务端
package com.alibaba.socket.server;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPSocketServer {
public static void main(String[] args) throws IOException {
method();
}
public static void method() throws IOException {
ServerSocket serverSocket = new ServerSocket(8888);
while (true) {
Socket accept = serverSocket.accept();
InputStream inputStream = accept.getInputStream();
BufferedInputStream bis = new BufferedInputStream(inputStream);
byte[] bytes = new byte[8192];
bis.read(bytes);
String s = new String(bytes).toUpperCase();
OutputStream outputStream = accept.getOutputStream();
outputStream.write(s.getBytes());
}
}
}
客户端
package com.alibaba.socket.client;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
public class TCPSocketClient {
public static void main(String[] args) throws IOException {
method();
}
public static void method() throws IOException {
Socket socket = new Socket("localhost", 8888);
OutputStream outputStream = socket.getOutputStream();
String content = "aaabbAbcd";
outputStream.write(content.getBytes());
byte[] bytes = new byte[8192];
InputStream inputStream = socket.getInputStream();
inputStream.read(bytes);
System.out.println(new String(bytes));
outputStream.close();
inputStream.close();
socket.close();
}
}
3.2 UDP通信
服务端
package com.alibaba.socket.server;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
public class UDPSocketServer {
public static void main(String[] args) throws IOException {
method();
}
public static void method() throws IOException {
DatagramSocket socket = new DatagramSocket(new InetSocketAddress("localhost", 8888));
byte[] bytes = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(bytes, 1024);
while (true) {
socket.receive(receivePacket);
byte[] data = receivePacket.getData();
String s = new String(data, StandardCharsets.UTF_8);
System.out.println(s);
s = s.toUpperCase();
byte[] b = s.getBytes();
DatagramPacket sendPacket = new DatagramPacket(b, b.length, receivePacket.getAddress(), receivePacket.getPort());
socket.send(sendPacket);
}
}
}
客户端
package com.alibaba.socket.client;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
public class UDPSocketClient {
public static void main(String[] args) throws IOException {
method();
}
public static void method() throws IOException {
DatagramSocket socket = new DatagramSocket();
String content = "aaabbAbcd";
byte[] bytes = content.getBytes();
DatagramPacket datagramPacket = new DatagramPacket(content.getBytes(), bytes.length,new InetSocketAddress("localhost",8888));
socket.send(datagramPacket);
byte[] result = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(result,1024);
socket.receive(receivePacket);
byte[] data = receivePacket.getData();
String s = new String(data, StandardCharsets.UTF_8);
System.out.println(s);
socket.close();
}
}
4. 参考资料
中科大郑烇、杨坚全套《计算机网络-自顶向下方法(第7版)》
JAVA Socket详解
|