计算机通讯模型
两种通讯模型介绍
OSI七层模型
:由国际标准化组织(ISO)和国际电报电话咨询委员会(CCITT)联合制定的开放系统互连参考模型
TCP/IP四层模型
:TCP/IP是一组用于实现网络互连的通信协议。Internet网络体系结构以TCP/IP为核心
共同点:分层概念、都能够提供面向连接
和无连接
两种通信服务机制
不同点:
由于OSI模型和协议比较复杂,所以并没有得到广泛的应用,而TCP/IP模型因其开放性和易用性在实践中得到了广泛的应用,TCP/IP协议栈也成为互联网的主流协议;
模型结构图
OSI七层模型
TCP/IP四层模型
Java Socket编程针对的就是tcp/ip通讯模型中的传输层
TCP/IP模型通讯要素
IP地址(IP Address)
IP地址(英语:Internet Protocol Address)是一种在Internet上的给主机编址的方式;
常见的IP地址,分为IPv4与IPv6两大类;
IP地址是网络上每台主机的唯一标识;
端口(Port)
主机中不同的应用有这不同的端口号,即端口号用于区别不同的应用;
主机端口号范围为0-65535,其中0-1023位为系统保留;
如常用的协议的端口号:HTTP 80、SSH 22、FTP 21、Telnet 23;
传输层协议(Protocol )
TCP (Transmission Control Protocol)
可靠传输:必须通讯双方连接成功才能通讯,这种操作称之为向连接
;
三次握手方式建立连接,四次握手端口连接;
UDP(User Datagram Protocol)
不可靠传输:无需双方连接成功就可以通讯,这种操作称之为无连接
;
速度比TCP传输要快,但可能会有数据丢包的情况,即数据可能不会被接受到 ,一般用于聊天程序;
Java Socket编程
部分工具类
InetAddress:解析地址
public class T1 {
public static void main(String[] args) throws Exception {
// 获取本机的InetAddress对象
InetAddress localHost = InetAddress.getLocalHost();
// 获取指定主机名称的InetAddress对象
InetAddress localHost2 = InetAddress.getByName("www.baidu.com");
System.out.println("主机名称:" + localHost.getHostName());
System.out.println("主机地址:" + localHost.getHostAddress());
System.out.println("===========================================");
System.out.println("主机名称:" + localHost2.getHostName());
System.out.println("主机地址:" + localHost2.getHostAddress());
/* 数据结果:
主机名称:DESKTOP-543IILF
主机地址:192.168.0.1
===========================================
主机名称:www.baidu.com
主机地址:14.215.177.38
* */
}
}
URL:解析url
public class T2 {
public static void main(String[] args) throws Exception {
/**
* 解析URL使用
*/
URL url = new URL("http://www.baidu.com");
System.out.println("协议:" + url.getProtocol());
System.out.println("主机(域名/ip地址):" + url.getHost());
System.out.println("端口:" + url.getPort());
// 如果URL方案或URL的URLStreamHandler未定义默认端口号,则返回-1
URLConnection connection = url.openConnection();
// 输出http://www.baidu.com的内容
InputStream in = connection.getInputStream();
byte[] buff = new byte[1024];
while(in.read(buff) != -1) {
System.out.println(new String(buff));
}
}
}
URLEncoder、URLDecoder:URL的编解码
public class T3 {
public static void main(String[] args) throws Exception {
String encode = URLEncoder.encode("http://www.baidu.com/123/张三", "GBK");
System.out.println(encode);
String gbk_decode = URLDecoder.decode(encode, "GBK");
System.out.println("GBK解码:" + gbk_decode);
/* 输出:
http%3A%2F%2Fwww.baidu.com%2F123%2F%D5%C5%C8%FD
GBK解码:http://www.baidu.com/123/张三
*/
}
}
TCP编程
服务端
// 注意:TCP通讯必须是服务端先启动
public class Server {
public static void main(String[] args) throws Exception {
ServerSocket server = new ServerSocket(55555);
Socket socket = null;
for(;;) {
// 监听接入服务器的连接
socket = server.accept();
// 读客户端
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 写客户端
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
/**
* 服务端是先读取内容后发送内容
*/
String text = null;
while((text=in.readLine()) != null) {
System.out.println("客服端:" + text);
out.write("by server"); // 写到缓存区
out.newLine(); /** 写入一个行分隔符,效果作用于readLine方法 */
out.flush(); // 刷新缓冲区
}
}
}
}
客户端
public class Client {
public static void main(String[] args) throws Exception {
InetAddress localHost = InetAddress.getLocalHost();
Socket socket = new Socket(localHost.getHostAddress(), 55555);
// 读控制台
Scanner scanner = new Scanner(System.in);
// 读服务器
BufferedReader readServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 写服务器
BufferedWriter outServer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
/**
* 客户端是先发送内容后读取内容
*/
String consoleText = null;
while((consoleText=scanner.nextLine()) != null) {
if("over".equals(consoleText.trim())) {
socket.shutdownOutput(); // 告诉服务端已经发送完信息,否者抛异常 Connect reset
System.exit(0); // 正常退出
}
outServer.write(consoleText); // 写到缓存区
outServer.newLine(); /** 写入一个行分隔符,效果作用于readLine方法 */
outServer.flush(); // 刷新缓冲区
System.out.println(readServer.readLine());
}
}
}
效果
UDP编程
服务端
/**
* UDP通信 服务器和客户端的port必须是不同的
* 先接受消息的就可以认为是服务端,阻塞等待数据包的到来
*/
public class Server {
public static void main(String[] args) throws Exception {
// 监听 55555 端口的消息
DatagramSocket datagramSocket = new DatagramSocket(55555);
for(;;) {
// 接收 55555 端口监听到的消息
byte[] buff = new byte[1024];
DatagramPacket cpacket = new DatagramPacket(buff, buff.length);
datagramSocket.receive(cpacket);
System.out.println("client:" + new String(buff, 0, buff.length));
// 发送消息到 44444 端口
byte[] cbuff = "by server".getBytes();
DatagramPacket spacket = new DatagramPacket(cbuff, cbuff.length, InetAddress.getLocalHost(), 44444);
datagramSocket.send(spacket);
}
}
}
客户端
public class Client {
public static void main(String[] args) throws Exception {
// 监听 44444 端口的消息
DatagramSocket datagramSocket = new DatagramSocket(44444);
// 发送消息
Scanner scanner = new Scanner(System.in);
String text = null;
while((text=scanner.nextLine()) != null) {
if("over".equals(text.trim())) {
System.exit(0); //正常退出
}
// 发送消息到 55555 端口
byte[] cbuff = text.trim().getBytes();
DatagramPacket cpacket = new DatagramPacket(cbuff, cbuff.length, InetAddress.getLocalHost(), 55555);
datagramSocket.send(cpacket);
// 接收 44444 端口监听到的消息
byte[] buff = new byte[1024];
DatagramPacket spacket = new DatagramPacket(buff, buff.length);
datagramSocket.receive(spacket);
System.out.println("server:" + new String(buff, 0, buff.length));
}
}
}
效果