欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java網(wǎng)絡(luò)編程之UDP實(shí)現(xiàn)原理解析

 更新時間:2021年09月04日 08:43:15   作者:計(jì)院阮小杰  
UDP實(shí)現(xiàn)通信非常簡單,沒有服務(wù)器,每個都是客戶端,每個客戶端都需要一個發(fā)送端口和一個接收端口,本文給大家介紹Java網(wǎng)絡(luò)編程之UDP實(shí)現(xiàn)原理解析,感興趣的朋友一起看看吧

UDP實(shí)現(xiàn)通信非常簡單,沒有服務(wù)器,每個都是客戶端,每個客戶端都需要一個發(fā)送端口和一個接收端口。一個客戶端向另一個客戶端發(fā)送消息時,需要知道對方的IP和接收端口,所用到的類為DatagramSocket。

DatagramSocket socket =new DatagramSocket(),發(fā)送端socket,若不指定端口,系統(tǒng)自動分配

DatagramSocket socket =new DatagramSocket("接收信息端口"),接收端socket,需要指定接收端口

​ 若想客戶端之間進(jìn)行全雙工通信,每個客戶端都要有兩個線程,一個用于發(fā)送信息,一個用于接收信息。

​ 那么UDP怎么實(shí)現(xiàn)私聊和群聊呢?(在本機(jī)一臺電腦的情況下實(shí)現(xiàn))

​ 首先私聊,客戶端向另一個客戶端發(fā)送消息,就要知道其IP(本機(jī)都是固定的localhost)和接收端口,也需要姓名進(jìn)行標(biāo)識,所以,每個客戶端都至少要自己的姓名和接收端口,而且端口不可重復(fù),否則會報(bào)端口被占用的錯。

​ 其次群聊,由于在本機(jī)一臺電腦上進(jìn)行,接收端口各不相同,所以廣播就不行了,此時就希望每個客戶端在啟動的時候,能夠把自己的姓名和接收端口給存起來,然后就可以遍歷進(jìn)行群聊。

​ 實(shí)現(xiàn):

  • 第一種,在每個客戶端啟動時,輸入自己的姓名和接收端口,發(fā)送信息時,需要輸入對方的接收端口號,如果輸入時輸入了多個端口,就是群發(fā)。那么這樣每次發(fā)送信息時都要指定對方的端口。。。
  • 第二種,客戶端啟動時,輸入姓名和接收端口,此時就把數(shù)據(jù)存起來,發(fā)送信息時,只用指定對方姓名即可。。??捎脭?shù)據(jù)庫存,可用文件存,我用的是XML來存。

要創(chuàng)建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)) {
				//如果此用戶已經(jīng)注冊過,直接把注冊時用的接收端口分配給他
				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();
		}
	}
}

發(fā)送信息:

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)) {
					//群聊,獲取所有用戶,不管對方在不在線,都發(fā)過去
					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) {
				//準(zhǔn)備接收包裹
				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根節(jié)點(diǎn),即users節(jié)點(diǎn)
			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;
	}
}

用戶實(shí)體類:

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 + "]";
	}
	
}

運(yùn)行結(jié)果:

到此這篇關(guān)于Java網(wǎng)絡(luò)編程之UDP實(shí)現(xiàn)原理解析的文章就介紹到這了,更多相關(guān)Java網(wǎng)絡(luò)編程UDP內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java的原子類無鎖并發(fā)利器詳解

    Java的原子類無鎖并發(fā)利器詳解

    這篇文章主要介紹了Java的原子類無鎖并發(fā)利器詳解,原子類同樣能夠解決互斥性問題、原子性問題除此之外,因?yàn)樵宇愂菬o鎖操作,沒有用互斥鎖解決帶來的加鎖解決性能消耗,這種絕佳方案是怎么做到的呢,需要的朋友可以參考下
    2023-12-12
  • IDEA集成Docker實(shí)現(xiàn)快捷部署的操作步驟

    IDEA集成Docker實(shí)現(xiàn)快捷部署的操作步驟

    這篇文章主要介紹了IDEA集成Docker實(shí)現(xiàn)快捷部署的操作步驟,通過靈活利用這一功能,開發(fā)人員可以更快速地開發(fā)、調(diào)試和部署應(yīng)用程序,從而提高開發(fā)工作的效率和質(zhì)量,需要的朋友可以參考下
    2024-06-06
  • Java使用Jedis操作Redis服務(wù)器的實(shí)例代碼

    Java使用Jedis操作Redis服務(wù)器的實(shí)例代碼

    本篇文章主要介紹了Java使用Jedis操作Redis服務(wù)器的實(shí)例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • Spring 加載多個xml配置文件的原理分析

    Spring 加載多個xml配置文件的原理分析

    我們知道Spring一次可以加載多個Bean定義的Xml配置文件,我們可以設(shè)想下如果讓我們來做我們會怎么做?我估計(jì)會根據(jù)配置文件的順序依次讀取并加載,那再來看看Spring是如何做的?
    2021-06-06
  • Springboot框架整合添加redis緩存功能

    Springboot框架整合添加redis緩存功能

    緩存就是一個存儲器,在技術(shù)選型中,常用?Redis?作為緩存數(shù)據(jù)庫。緩存主要是在獲取資源方便性能優(yōu)化的關(guān)鍵方面。Redis?是一個高性能的?key-value?數(shù)據(jù)庫,接下來通過本文給大家介紹Springboot框架整合添加redis緩存功能,感興趣的朋友一起看看吧
    2021-11-11
  • mybatisplus自動填充屬性值的實(shí)現(xiàn)步驟

    mybatisplus自動填充屬性值的實(shí)現(xiàn)步驟

    MyBatis-Plus提供自動填充的功能,幫助自定設(shè)置這些字段的值,提升開發(fā)效率,本文就來介紹一下如何使用,感興趣的可以了解一下
    2023-12-12
  • java寫卷積神經(jīng)網(wǎng)絡(luò)(CupCnn簡介)

    java寫卷積神經(jīng)網(wǎng)絡(luò)(CupCnn簡介)

    這篇文章主要介紹了java寫卷積神經(jīng)網(wǎng)絡(luò)(CupCnn簡介),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04
  • Java動態(tài)代理的示例詳解

    Java動態(tài)代理的示例詳解

    動態(tài)代理指的是,代理類和目標(biāo)類的關(guān)系在程序運(yùn)行的時候確定的,客戶通過代理類來調(diào)用目標(biāo)對象的方法,是在程序運(yùn)行時根據(jù)需要動態(tài)的創(chuàng)建目標(biāo)類的代理對象。本文將通過案例詳細(xì)講解一下動態(tài)代理,需要的可以參考一下
    2022-02-02
  • springboot全局異常處理代碼實(shí)例

    springboot全局異常處理代碼實(shí)例

    這篇文章主要介紹了springboot全局異常處理代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-01-01
  • Java Synchronized字節(jié)碼層分析體驗(yàn)

    Java Synchronized字節(jié)碼層分析體驗(yàn)

    這篇文章主要介紹了Java Synchronized字節(jié)碼層分析,synchronized關(guān)鍵字解決了多個線程之間的資源同步性,synchronized關(guān)鍵字保證了它修飾的方法或者代碼塊任意時刻只有一個線程在訪問
    2023-04-04

最新評論