网络编程—Socket套接字(UDP)
上篇文章:网络编程—网络概念https://csdnimg.cn/release/blog_editor_html/release2.3.8/ckeditor/plugins/CsdnLink/icons/icon-default.png?t=P1C7https://blog.csdn.net/sniper_fandc/article/details/146923380?fromshare=blogdetail&sharetype=blogdetail&sharerId=146923380&sharerefer=PC&sharesource=sniper_fandc&sharefrom=from_link
目录
1 概念
2 Socket套接字
3 UDP数据报套接字
1 概念
(1)网络编程:指网络上的主机,通过不同的进程,以编程的方式实现网络通讯(网络数据传输)。
进程具有隔离性,因此不同的进程间要通讯就得通过共享的公共区域来交换数据,网卡便是一种共享公共区域。
(2)客户端(Client)/服务器(Server):客户端是数据发送方,服务器是数据接收方,由于服务器是被动接收数据,不知道客户端什么时候发送数据,因此服务器经常是24小时运行。
(3)哀求(request)和相应(response):客户端发送给服务器的数据,服务器返回给客户端的数据。
(4)客户端/服务器交互方式:一问一答(浏览网页)、多问一答(上传文件)、一问多答(下载文件)和多问多答(远程控制、游戏串流(手机毗连电脑玩电脑游戏))。
2 Socket套接字
Socket便是传输层(操纵体系)提供给步调员的API,有基于TCP和UDP两种范例,原始的API是C语言的,经过JVM包装后,形成了Java的Socket API。
3 UDP数据报套接字
基于UDP的Socket重要是DatagramSocket,用于发送和接收UDP数据报,作用和操纵方式都类似文件(打开Socket文件(对应网卡),发送/接收数据报,关闭文件)。
构造方法/方法
含义
DatagramSocket()
构造方法,创建一个UDP数据报套接字的Socket,绑定到本机任意一个随机端口(一般用于客户端)
DatagramSocket(int port)
构造方法,创建一个UDP数据报套接字的Socket,绑定到本机指定的端口(一般用于服务端)
void receive(DatagramPacket p)
从套接字接收数据报(如果没有接收到数据报,该方法会阻塞等候)
void send(DatagramPacket p)
从套接字发送数据报包(不会阻塞等候,直接发送)
void close()
关闭数据报套接字
DatagramPacket是数据报的API,用来构造必要发送和接收的数据。
构造方法/方法
含义
DatagramPacket(byte[] buf, int length)
构造方法,创建一个DatagramPacket用来接收数据报,接收的数据生存在buf,length是数据长度
DatagramPacket(byte[] buf, int offset, int length, SocketAddress address
构造方法,创建一个DatagramPacket用来发送数据报,发送的数据生存在buf,offset是起始下标,length是数据长度,address指定目标主机的IP和端标语
InetAddress getAddress()
从接收的数据报中,获取发送端主机IP地点,或从发送的数据报中,获取接收端主机IP地点
int getPort()
从接收的数据报中,获取发送端主机的端标语,或从发送的数据报中,获
取接收端主机端标语
byte[] getData()
获取数据报中的数据
而使用InetSocketAddress(InetAddress addr, int port)即可创建一个Socket地点,包罗IP地点和端标语,它是SocketAddress的子类。
下面利用UDP数据报套接字实现一个回显服务器,回显服务器是指客户端发送什么,服务器就返回什么。
public class UdpServer {
//回显服务器端口号
private final int PORT = 8000;
public DatagramSocket datagramSocket = null;
//通过端口创建udp服务器(本质是打开一个socket文件)
public UdpServer() throws SocketException {
datagramSocket = new DatagramSocket(PORT);
}
//启动服务器
public void start() throws IOException {
System.out.println("服务器已启动");
//服务器需要24小时启动因此写成死循环
while(true){
//1.创建接收请求的数据报(分配字节数组空间)并接收请求
DatagramPacket datagramPacket = new DatagramPacket(new byte,4096);
//该方法会一直阻塞等待直到客户端发送请求
datagramSocket.receive(datagramPacket);
//2.解析请求构造响应数据报
String request = new String(datagramPacket.getData(),0,datagramPacket.getLength());
//3.根据请求构造响应(服务器业务逻辑)
String response = process(request);
//要用指定发送地址的构造方法(发送地址可以从接收的请求数据报中获取)
DatagramPacket datagramPacketResponse = new DatagramPacket(response.getBytes(),response.getBytes().length,
datagramPacket.getSocketAddress());
//4.返回响应
datagramSocket.send(datagramPacketResponse);
System.out.printf("[%s:%d] request=%s;response=%s\n",datagramPacket.getAddress().toString(),datagramPacket.getPort(),
request,response);
}
}
//回显服务器就是发送什么请求返回什么响应
private String process(String request) {
return request;
}
public static void main(String[] args) throws IOException {
//启动服务器
UdpServer server = new UdpServer();
server.start();
}
}
public class UdpClient {
//创建客户端
private DatagramSocket socket = null;
public UdpClient() throws SocketException {
//客户端一般随机生成端口号
socket = new DatagramSocket();
}
//启动客户端
public void start() throws IOException {
Scanner scanner = new Scanner(System.in);
while(true){
//1.构造请求
System.out.print(">");
String req = scanner.next();
//构造的请求数据报既要包含数据又要包含地址(IP+端口)
DatagramPacket request = new DatagramPacket(req.getBytes(),req.getBytes().length,
InetAddress.getByName("127.0.0.1"),8000);
//2.发送请求
socket.send(request);
//3.接受响应并解析响应
DatagramPacket response = new DatagramPacket(new byte,4096);
socket.receive(response);
String resp = new String(response.getData(),0,response.getLength());
//4.将响应返回给用户
System.out.printf("request=%s,response=%s\n",req,resp);
}
}
public static void main(String[] args) throws IOException {
UdpClient udpClient = new UdpClient();
udpClient.start();
}
} 在服务器代码中,必要注意response.getBytes().length不等于response.length(),前一个方法获取的是字节长度,而后一个方法获取的是字符长度,当字符中有中文时,字节长度和字符长度并不相等,因此不能替换。而字符串“127.0.0.1”是环回IP,表示本机(自己发给自己)。
https://i-blog.csdnimg.cn/direct/af4bc4fca49145c6b7069b303d16ad92.png
https://i-blog.csdnimg.cn/direct/b1447af3fa9c4505a68be178a208994b.png
根据结果显示,虽然发送的一条哀求hello World,但是却被拆成hello和World两条哀求发送了,这是因为这里使用Scanner类的next()方法,该方法以空格作为结束举行分割,因此发送两条哀求。如果向发送一条,就可以使用nextLine(),该方法以换行符结束。
下篇文章:
网络编程—Socket套接字(TCP)https://csdnimg.cn/release/blog_editor_html/release2.3.8/ckeditor/plugins/CsdnLink/icons/icon-default.png?t=P1C7https://blog.csdn.net/sniper_fandc/article/details/146923783?fromshare=blogdetail&sharetype=blogdetail&sharerId=146923783&sharerefer=PC&sharesource=sniper_fandc&sharefrom=from_link
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]