您的位置:首页 > 理论基础 > 计算机网络

java基础--网络编程之UDP

2012-11-22 16:22 399 查看
笔记摘要:

本篇博客首先对网络通信要素和网络通讯中两种常见协议:UDP和TCP进行了介绍,另外对于UDP协议下实现通信的接收端和发送端,

并最终通过多线程的群聊服务端对UDP的学习进行了总结。

一、网络通讯要素

IP地址:InetAddress

网络中设备的标识
不易记忆,可用主机名
本地回环地址:127.0.0.1 主机名:localhost

端口号

用于标识进程的逻辑地址,不同进程的标识
有效端口:0~65535,其中0~1024系统使用或保留端口

传输协议

通讯的规则
常见协议:TCP ,UDP


二、网络参考模型图




三、UDP与TCP特点

UDP

将数据及源和目的封装成数据包中,不需要建立连接
每个数据包的大小限制在64K内
因无连接,是不可靠协议
不需要建立连接,速度快

应用:聊天软件、视频会议、对话机

TCP

建立连接,形成传输数据的通道,对方必须存在
在连接中进行大量数据传输
通过三次握手完成连接,是可靠协议
必须建立连接,效率会稍低

应用:电话通信

四、Socket

Socket就是为网络服务提供的一种机制,通信的两端都有Socket,网络通信其实就是Socket间的通信
数据在两个Socket间通过传输。

五、UDP传输的使用

通过简单的UDP客户端与接收端学会如何创建一个UDP服务

udp发送端

需求:通过udp传输方式,将一段文字数据发送出去

思路:

1,建立updsocket服务。
2,提供数据,并将数据封装到数据包中。
3,通过socket服务的发送功能,将数据包发出去。
4,关闭资源。

简单的UDP发送端

import java.net.*;

class  UdpSend
{
	public static void main(String[] args) throws Exception
	{
		//1,创建udp服务。通过DatagramSocket对象。
		DatagramSocket ds = new DatagramSocket(8888);

		//2,确定数据,并封装成数据包。DatagramPacket(byte[] buf, int length, InetAddress address, int port) 

		byte[] buf = "udp ge men lai le ".getBytes();
		DatagramPacket dp = 
			new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.254"),10000);

		//3,通过socket服务,将已有的数据包发送出去。通过send方法。
		ds.send(dp);

		//4,关闭资源。
		ds.close();

	}
}


简单的UDP接收端:用于接收udp协议传输的数据并处理

思路:

1,定义udpsocket服务。通常会监听一个端口。其实就是给这个接收网络应用程序定义数字标识。

方便于明确哪些数据过来该应用程序可以处理。

2,定义一个数据包,因为要存储接收到的字节数据。

因为数据包对象中有更多功能可以提取字节数据中的不同数据信息。

3,通过socket服务的receive方法将收到的数据存入已定义好的数据包中。

4,通过数据包对象的特有功能。将这些不同的数据取出。打印在控制台上。

5,关闭资源。

简单的UDP接收端代码

class  UdpRece
{
	public static void main(String[] args) throws Exception
	{
		//1,创建udp socket,建立端点。
		DatagramSocket ds = new DatagramSocket(10000);
		while(true)
		{
		//2,定义数据包。用于存储数据。
		byte[] buf = new byte[1024];
		DatagramPacket dp = new DatagramPacket(buf,buf.length);

		//3,通过服务的receive方法将收到数据存入数据包中。
		ds.receive(dp);//阻塞式方法。
		

		//4,通过数据包的方法获取其中的数据。
		String ip = dp.getAddress().getHostAddress();
		String data = new String(dp.getData(),0,dp.getLength());
		int port = dp.getPort();
		System.out.println(ip+"::"+data+"::"+port);

		}
		//5,关闭资源
		//ds.close();

	}
}


五、使用键盘录入的UDP接收端和服务端

使用while实现循环发送和接收

import java.net.*;
import java.io.*;
class  UdpS2
{
	public static void main(String[] args) throws Exception
	{
		DatagramSocket ds = new DatagramSocket();

		//键盘录入
		BufferedReader bufr = 
			new BufferedReader(new InputStreamReader(System.in));

		String line = null;

		while((line=bufr.readLine())!=null)
		{
			if("886".equals(line))		//当输入内容为“886”,键盘录入结束
				break;

			byte[] buf = line.getBytes();

			DatagramPacket dp = 
				new DatagramPacket(buf,buf.length,InetAddress.getByName("169.254.57.236"),10002);

			ds.send(dp);
		}
		ds.close();
	}
}

class  UdpR2
{
	public static void main(String[] args) throws Exception
	{
		DatagramSocket ds = new DatagramSocket(10002);

		while(true)
		{
			byte[] buf = new byte[1024];
			DatagramPacket dp = new DatagramPacket(buf,buf.length);

			ds.receive(dp);

			String ip = dp.getAddress().getHostAddress();
			String data = new String(dp.getData(),0,dp.getLength());
			

			System.out.println(ip+"::"+data);
		}
	}
}


广播的发送:

169.254.57.236 末尾如果是".0"网络段,".255"代表.网络段的广播地址,该网络段所有开启接收端的机器都能收到信息。

六、简单的多线程的群聊软件

需求:接收和发送在一个进程中执行

思路:

有收数据的部分,和发数据的部分。这两部分需要同时执行,那就需要用到多线程技术。

一个线程控制收,一个线程控制发。

因为收和发动作是不一致的,所以要定义两个run方法,而且这两个方法要封装到不同的类中。



模拟聊天室效果:

运行该聊天室,可以接收其他窗口发送过来的数据,也可以向其他用户发送数据,为了模拟聊天的效果,所以我们另外开一些窗口,

这些窗口只需开启一个发送端即可,所有窗口发送的数据最终会显示在聊天室窗口上。

多线程群聊实现代码

import java.io.*;
import java.net.*;

class  ChatDemo
{
	public static void main(String[] args) throws Exception
	{
		DatagramSocket sendSocket = new DatagramSocket();
		DatagramSocket receSocket = new DatagramSocket(10002);

		new Thread(new Send(sendSocket)).start();
		new Thread(new Rece(receSocket)).start();
	}
}

class Send implements Runnable
{
	private DatagramSocket ds;
	public Send(DatagramSocket ds)
	{
		this.ds = ds;
	}

	public void run()
	{
		try
		{
			BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
			String line = null;
			while((line=bufr.readLine())!=null)
			{	
				byte[] buf = line.getBytes();

				DatagramPacket dp = 
					new DatagramPacket(buf,buf.length,InetAddress.getByName("169.254.26.235"),10002);

				ds.send(dp);

				if("886".equals(line))
					break;
			}
		}
		catch (Exception e)
		{
			throw new RuntimeException("发送端失败");
		}
	}
}

class Rece implements Runnable
{
	private DatagramSocket ds;
	public Rece(DatagramSocket ds)
	{
		this.ds = ds;
	}
	public void run()
	{
		try
		{
			while(true)
			{
				byte[] buf = new byte[1024];
				DatagramPacket dp = new DatagramPacket(buf,buf.length);
				ds.receive(dp);

				String ip = dp.getAddress().getHostAddress();
				String data = new String(dp.getData(),0,dp.getLength());

				if("886".equals(data))
				{
					System.out.println(ip+"....离开聊天室");
					break;
				}

				System.out.println(ip+":"+data);
			}
		}
		catch (Exception e)
		{
			throw new RuntimeException("接收端失败");
		}
	}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: