大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺
一、网络编程基础
计算机网络是指两台或更多的计算机组成的网络,在同一个网络中,任意两台计算机都可以直接通信,因为所有计算机都需要遵循同一种网络协议。因此,为了把计算机网络接入互联网,就必须使用TCP/IP协议。
1.常用协议
IP协议只负责发数据包,不保证顺序和正确性,而TCP协议负责控制数据包传输,它在传输数据之前需要先建立连接,建立连接后才能传输数据,传输完后还需要断开连接。
UDP协议(User Datagram Protocol)是一种数据报文协议,它是无连接协议,不保证可靠传输。因为UDP协议在通信前不需要建立连接,因此它的传输效率比TCP高,而且UDP协议比TCP协议要简单得多。选择UDP协议时,传输的数据通常是能容忍丢失的,例如,一些语音视频通信的应用会选择UDP协议。
2.什么是Socket?
Socket是一个抽象概念,一个应用程序通过一个Socket来建立一个远程连接,而Socket内部通过TCP/IP协议把数据传输到网络。可以把Socket简单理解为IP地址加端口号。端口号总是由操作系统分配,它是一个0~65535之间的数字,其中,小于1024的端口属于特权端口,需要管理员权限,大于1024的端口可以由任意用户的应用程序打开。
因此,当Socket连接成功地在服务器端和客户端之间建立后:对服务器端来说,它的Socket是指定的IP地址和指定的端口号;对客户端来说,它的Socket是它所在计算机的IP地址和一个由操作系统分配的随机端口号。
UDP端口和TCP端口虽然都使用0~65535,但他们是两套独立的端口,即一个应用程序用TCP占用了端口1234,不影响另一个应用程序用UDP占用端口1234
二、服务器端
要使用Socket编程,我们首先要编写服务器端程序。Java标准库提供了ServerSocket来实现对指定IP和指定端口的监听。ServerSocket的典型实现代码如下:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.HashMap;
import java.util.Map;
public class WorkDisctServer {
public static void main(String[] args) {
Map<String, String> wordMap = new HashMap<String, String>(){
{
put("one", "壹");
put("two", "贰");
put("three", "叁");
put("four", "肆");
put("five", "伍");
put("six", "陆");
put("serven", "柒");
}
};
try (DatagramSocket serverSocket = new DatagramSocket(7788)) {
while(true) {
// 准备"空"数据包
byte[] buff = new byte[1024];// 原始的字节数组
DatagramPacket packet = new DatagramPacket(buff, buff.length);
// 读取(客户端发送的英文单词)
// 接收数据包
serverSocket.receive(packet);
// 获取数据包中的"数据"(字节数组)
// 获取数据包中的“读取位置”(int类型)
// 获取数据包中的“长度”
String word = new String(
packet.getData(),
packet.getOffset(),
packet.getLength());
System.out.println("【服务器】:获取来自客服端的单词"+word);
String chinese = wordMap.get(word);
if(chinese == null) {
chinese = "未知结果";
}
//发送(向客户端发送中文释义)
byte[] resultbuff = chinese.getBytes();
packet.setData(resultbuff);
serverSocket.send(packet);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
三、客户端
和服务器端相比,客户端使用UDP时,只需要直接向服务器端发送UDP包,然后接收返回的UDP包:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.util.Scanner;
public class WorkDictClient {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
while (true) {
String word = input.nextLine();
if (word.equals("end")) {
break;
}
// 创建基于UDP协议的DatagramSocket对象
try (DatagramSocket clientSocket = new DatagramSocket()) {
// timeout超时
clientSocket.setSoTimeout(2000);
// 连接服务器(服务器IP和端口)
clientSocket.connect(new InetSocketAddress("192.168.254.178", 7788));
// 发送(向服务发送一个英文单词)
// String word = "one";
byte[] wordbuff = word.getBytes();// 获取英文单词字符串的字节数组
// 封装成DatagramPacket对象(数据包)
DatagramPacket packet = new DatagramPacket(wordbuff, wordbuff.length);
// 发送数据包
clientSocket.send(packet);
// 读取
byte[] resultbuff = new byte[1024];
DatagramPacket resultPacket = new DatagramPacket(resultbuff, resultbuff.length);
clientSocket.receive(resultPacket);
String result = new String(resultPacket.getData(), resultPacket.getOffset(), resultPacket.getLength());
System.out.println("来自服务器的中文释义" + result);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
区别:
1.客户端创建DatagramSocket实例时并不需要指定端口,而是由操作系统自动指定一个当前未使用的端口。紧接着,调用setSoTimeout(1000)设定超时1秒,意思是后续接收UDP包时,等待时间最多不会超过1秒,否则在没有收到UDP包时,客户端会无限等待下去。这一点和服务器端不一样,服务器端可以无限等待,因为它本来就被设计成长时间运行。
2.如果客户端希望向两个不同的服务器发送UDP包,那么它必须创建两个DatagramSocket实例。后续的收发数据和服务器端是一致的。通常来说,客户端必须先发UDP包,因为客户端不发UDP包,服务器端就根本不知道客户端的地址和端口号。
易混淆知识点:
1.注意到客户端的DatagramSocket还调用了一个connect()方法“连接”到指定的服务器端。不是说UDP是无连接的协议吗?为啥这里需要connect()?
这个connect()方法不是真连接,它是为了在客户端的DatagramSocket实例中保存服务器端的IP和端口号,确保这个DatagramSocket实例只能往指定的地址和端口发送UDP包,不能往其他地址和端口发送。这么做不是UDP的限制,而是Java内置了安全检查。
2.如果客户端认为通信结束,就可以调用disconnect()断开连接。
disconnect()也不是真正地断开连接,它只是清除了客户端DatagramSocket实例记录的远程服务器地址和端口号.这样,DatagramSocket实例就可以连接另一个服务器端。
四、实现结果:
知识小结:
- 使用UDP协议通信时,服务器和客户端双方无需建立连接;
- 服务器端用DatagramSocket(port)监听端口;
- 客户端使用DatagramSocket.connect()指定远程地址和端口;
- 双方通过receive()和send()读写数据;
- DatagramSocket没有IO流接口,数据被直接写入byte[]缓冲区;
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/195885.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...