1. UDP协议
这里我们首先需要明白一点,UDP本身就是一种不需要连的协议,所以是不存在客户端与服务端的.
我们通常是通过发送方与接收方的概念来区分,但是我们又需要明白一点发送方与接收方可能是同一个机器.
1.1 UDP消息发送1.0
这里我们还是通过代码来讲解,并且这里我们还是分两个部分来讲.
一是发送方,另一个就是接收方
发送方:
public static void main(String[] args) throws Exception { //建立一个DatagramSocket对象,这里同时我们也开放他的6666端口号,只要开放端口号之后就不存在是发送方还是接收方的概念了,既可以是发送方,也可以是接收方. DatagramSocket socket=new DatagramSocket(6666); //发送的信息 String msg="你好啊,服务器!"; //发送的对象的ip地址以及端口号 InetAddress localhost=InetAddress.getByName("localhost"); int port=9999; //发送的数据报的各类信息,数据的起始位置,接收方的ip及端口号 DatagramPacket packet=new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,localhost,port); //发送数据报 socket.send(packet); }
接收方:
public static void main(String[] args) throws Exception{ //开放端口 DatagramSocket socket=new DatagramSocket(9999); //接收数据报 byte[]buffer=new byte[1024]; DatagramPacket packet=new DatagramPacket(buffer,0,buffer.length); //阻塞接受将信息存入到packet对象之中 socket.receive(packet); //打印数据 System.out.println(packet.getAddress().getHostAddress()); System.out.println(new String(packet.getData(),0,packet.getLength())); //关闭连接 socket.close(); }
其实从上面我们也能够看出来UDP就是不需要连接的,因为整个的过程中我们都没有看到ServerSocket这个对象,而是通过 DatagramSocket 这个对象来进行.
其次就是之前我们都是通过 流的形式 来进行数据的传输,但是在UDP中我们则是通过 数据报 的形式来进行,这里其实如果大家学过计算机网络这门课程的话,应该就懂了.
实际效果:
1.2 UDP消息发送2.0
上面的是我们只能在程序中规定好消息,然后发送,并且整个过程是一次性的,程序执行完就没有了,现在我们编写的就是能够通过键盘输入并且传递信息,并且接收能够持续接受信息,只有当接收到bye这样一个关键字时,我们才退出整个程序.
发送方:
public static void main(String[] args) throws Exception { DatagramSocket socket=new DatagramSocket(9999); while (true){ BufferedReader Reader=new BufferedReader(new InputStreamReader(System.in)); String data= Reader.readLine(); byte [] bytes=data.getBytes(); DatagramPacket packet=new DatagramPacket(bytes,0,bytes.length,new InetSocketAddress("localhost",8888)); socket.send(packet); if(data.equals("bye")) break; } socket.close(); }
接收方:
public static void main(String[] args) throws Exception { DatagramSocket socket=new DatagramSocket(8888); while (true){ byte[] bytes=new byte[1024]; DatagramPacket packet=new DatagramPacket(bytes,0,bytes.length);//阻塞式接收包裹 socket.receive(packet); byte[]newdata=packet.getData(); String data=new String(newdata,0,newdata.length); System.out.println(data); if(data.equals("bye")) break; } socket.close(); }
实际效果:
1.3 UDP多线程聊天
这里我们会运用到多线程的理念,如果有不了解的建议先去了解一下之后再来学习.
这里我们主要为发送方与接收方两个角色各创建一个线程
TalkSend
public class TalkSend implements Runnable { DatagramSocket socket=null; BufferedReader Reader=null; private String toip; private int fromport; private int toport; public TalkSend(String toip, int fromport, int toport) throws Exception { this.toip = toip; this.fromport = fromport; this.toport = toport; socket=new DatagramSocket(fromport); Reader=new BufferedReader(new InputStreamReader(System.in)); } @Override public void run() { while (true){ try { String data= Reader.readLine(); byte [] bytes=data.getBytes(); DatagramPacket packet=new DatagramPacket(bytes,0,bytes.length,new InetSocketAddress(this.toip,this.toport)); socket.send(packet); if(data.equals("bye")) break; }catch (Exception e){ e.printStackTrace(); } } socket.close(); } }
TalkReceive
public class TalkReceive implements Runnable { DatagramSocket socket=null; private String msgfrom; private int port; public TalkReceive(String msgfrom,int port) throws SocketException { this.msgfrom=msgfrom; this.port = port; socket=new DatagramSocket(port); } @Override public void run() { while (true){ try { byte[] bytes=new byte[1024]; DatagramPacket packet=new DatagramPacket(bytes,0,bytes.length); socket.receive(packet); byte[]newdata=packet.getData(); String data=new String(newdata,0,newdata.length); System.out.println(msgfrom+":"+data); if(data.equals("bye")) break; }catch (Exception e){ e.printStackTrace(); } } socket.close(); } }
创建完发送与接收线程之后,我们就可以创建学生与老师两个用户来实现这个聊天程序.
学生:
public class TalkStudent { public static void main(String[] args) throws Exception { new Thread(new TalkSend("localhost",7777,9999)).start(); new Thread(new TalkReceive("老师",8888)).start(); } }
教师:
public class TalkTeacher { public static void main(String[] args) throws Exception { new Thread(new TalkSend("localhost",5555,8888)).start(); new Thread(new TalkReceive("学生",9999)).start(); } }
这里我们只需要稍微注意一下端口号的对应就行了
实际效果:
里出现中文乱码主要是因为cmd是通过GBK来进行编码的,这里可以自己去设置成UTF-8的编码方式.


