这篇文章主要讲解了“Java网络编程UDP的实现原理”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java网络编程UDP的实现原理”吧!
UDP实现通信非常简单,没有服务器,每个都是客户端,每个客户端都需要一个发送端口和一个接收端口。一个客户端向另一个客户端发送消息时,需要知道对方的IP和接收端口,所用到的类为DatagramSocket。
DatagramSocket socket =new DatagramSocket(),发送端socket,若不指定端口,系统自动分配
DatagramSocket socket =new DatagramSocket("接收信息端口"),接收端socket,需要指定接收端口
若想客户端之间进行全双工通信,每个客户端都要有两个线程,一个用于发送信息,一个用于接收信息。
那么UDP怎么实现私聊和群聊呢?(在本机一台电脑的情况下实现)
首先私聊,客户端向另一个客户端发送消息,就要知道其IP(本机都是固定的localhost)和接收端口,也需要姓名进行标识,所以,每个客户端都至少要自己的姓名和接收端口,而且端口不可重复,否则会报端口被占用的错。
其次群聊,由于在本机一台电脑上进行,接收端口各不相同,所以广播就不行了,此时就希望每个客户端在启动的时候,能够把自己的姓名和接收端口给存起来,然后就可以遍历进行群聊。
实现:
第一种,在每个客户端启动时,输入自己的姓名和接收端口,发送信息时,需要输入对方的接收端口号,如果输入时输入了多个端口,就是群发。那么这样每次发送信息时都要指定对方的端口。。。
第二种,客户端启动时,输入姓名和接收端口,此时就把数据存起来,发送信息时,只用指定对方姓名即可。。。可用数据库存,可用文件存,我用的是XML来存。
要创建xml文件,路径在Operation类中
UdpClient.java:
public class UdpClient { public static void main(String[] args) { try { Scanner scanner = new Scanner(System.in); User user = new User(); System.out.print("请输入用户名》》"); String userName = scanner.next(); if (Operation.userIsExist(userName)) { //如果此用户已经注册过,直接把注册时用的接收端口分配给他 user = Operation.findUserByName(userName); }else { //未注册,用户自己指定端口 while(true) { System.out.println("请输入接收端口》》"); int port = Integer.parseInt(scanner.next()); if (Operation.portIsExist(port)) { System.err.println("该端口已被使用,请重新输入。。。。"); continue; }else { user.setName(userName); user.setPort(port); Operation.addUser(user); break; } } } new Thread(new SendMsg(user)).start(); new Thread(new ReceiveMsg(user)).start(); } catch (Exception e) { e.printStackTrace(); } } }
发送信息:
public class SendMsg implements Runnable{ private User self = null; private DatagramSocket socket = null; private BufferedReader reader = null; public SendMsg(User self) { try { socket = new DatagramSocket(); reader = new BufferedReader(new InputStreamReader(System.in)); this.self = self; } catch (Exception e) { e.printStackTrace(); } } @Override public void run() { try { while(true) { String[] msg = reader.readLine().split("@"); if (msg.length != 2) { System.err.println("注意格式:消息@对方名字(私聊)或all(群聊)"); continue; } msg[0] = self.getName()+"说:"+msg[0]; byte[] data = msg[0].getBytes(); String toPerson = msg[1]; if (("all").equals(toPerson)) { //群聊,获取所有用户,不管对方在不在线,都发过去 List<User> users = Operation.getUsers(); for(User user:users) { if (self != user) { DatagramPacket packet = new DatagramPacket(data, 0,data.length,new InetSocketAddress("localhost",user.getPort())); socket.send(packet); } } }else { //私聊 try { DatagramPacket packet = new DatagramPacket(data, 0,data.length,new InetSocketAddress("localhost",Operation.findUserByName(toPerson).getPort())); socket.send(packet); } catch (Exception e) { System.out.println("对方不在线。。。"); } } } } catch (Exception e) { e.printStackTrace(); } } }
接收消息:
public class ReceiveMsg implements Runnable{ private DatagramSocket socket = null; public ReceiveMsg(User user) { try { socket = new DatagramSocket(user.getPort()); } catch (Exception e) { e.printStackTrace(); } } @Override public void run() { try { while(true) { //准备接收包裹 byte[] container = new byte[1024]; DatagramPacket packet = new DatagramPacket(container,0,container.length); socket.receive(packet); byte[]data = packet.getData(); String receiveData = new String(data, 0, data.length); System.out.println(receiveData); } } catch (Exception e) { e.printStackTrace(); } socket.close(); } }
操作XML文件类:
public class Operation { private static String FILE_PATH = "config/user.xml"; //文件目录 //在xml文件中添加一个用户信息 public static void addUser(User user) { InputStream in = null; SAXReader reader = new SAXReader(); Document doc = null; try { in = new FileInputStream(FILE_PATH); doc = reader.read(in); Element root = doc.getRootElement(); //获取xml根节点,即users节点 Element element = root.addElement("user"); element.addElement("name").addText(user.getName()); element.addElement("port").addText(String.valueOf(user.getPort())); FileOutputStream fos = new FileOutputStream(FILE_PATH); //格式化xml文件 OutputFormat format = OutputFormat.createPrettyPrint(); format.setEncoding("utf-8"); XMLWriter writer = new XMLWriter(fos,format); writer.write(doc); writer.close(); } catch (Exception e) { System.out.println("error"); } finally { try { if(in != null) in.close(); } catch (IOException e) { System.out.println("error"); } } } //列出xml中所有用户信息 public static List<User> getUsers() { InputStream in = null; SAXReader reader = new SAXReader(); Document doc = null; List<User> users = new ArrayList<>(); try { in = new FileInputStream(FILE_PATH); doc = reader.read(in); Element root = doc.getRootElement(); List<Element> elements = root.elements(); for (Element element : elements) { User user = new User(); user.setName(element.elementText("name")); user.setPort(Integer.valueOf(element.elementText("port"))); users.add(user); } } catch (Exception e1) { System.out.println("error"); } finally { try { in.close(); } catch (IOException e) { System.out.println("error"); } } return users; } public static User findUserByName(String name) { InputStream in = null; SAXReader reader = new SAXReader(); Document doc = null; try { in = new FileInputStream(FILE_PATH); doc = reader.read(in); Element root = doc.getRootElement(); List<Element> elements = root.elements(); for (Element element : elements) { if(name != null && name.equals(element.elementText("name"))) { User user = new User(); user.setName(name); user.setPort(Integer.parseInt(element.elementText("port"))); return user; } } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (DocumentException e) { e.printStackTrace(); } return null; } public static boolean portIsExist(int port) { InputStream in = null; SAXReader reader = new SAXReader(); Document doc = null; try { in = new FileInputStream(FILE_PATH); doc = reader.read(in); Element root = doc.getRootElement(); List<Element> elements = root.elements(); for (Element element : elements) { if(port == Integer.parseInt(element.elementText("port"))) return true; } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (DocumentException e) { e.printStackTrace(); } return false; } //判断某个用户是否存在该xml中 public static boolean userIsExist(String name) { InputStream in = null; SAXReader reader = new SAXReader(); Document doc = null; try { in = new FileInputStream(FILE_PATH); doc = reader.read(in); Element root = doc.getRootElement(); List<Element> elements = root.elements(); for (Element element : elements) { if(name != null && name.equals(element.elementText("name"))) return true; } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (DocumentException e) { e.printStackTrace(); } return false; } }
用户实体类:
public class User implements Serializable{ private String name;//姓名 private int port;//接收端口 public String getName() { return name; } public int getPort() { return port; } public void setName(String name) { this.name = name; } public void setPort(int port) { this.port = port; } @Override public String toString() { return "User [name=" + name + ", port=" + port + "]"; } }
运行结果:
感谢各位的阅读,以上就是“Java网络编程UDP的实现原理”的内容了,经过本文的学习后,相信大家对Java网络编程UDP的实现原理这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。