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内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!