黑马程序员_ 网络编程(1) UDP

本文介绍了网络编程的基本概念,包括IP地址、端口号、传输协议等,对比了TCP与UDP的特点及应用场景,并通过示例代码展示了如何使用Java进行UDP数据传输。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

-------  android培训java培训、期待与您交流! ----------

一.概述

实现不同主机上的数据通信,而要实现通讯则需要首先知道对方的IP和端口号,同时明确双方使用的通信规则,或传输协议
IP地址:主机在网络的地址,或者在网上的唯一标识
端口号:数据要发送到对方指定的应用程序上,为了标识这些应用程序,所以给这些网络应用程序都用数字进行标识,为了方便称呼这个数字,就这个数组叫为“端口”,或“逻辑端口”,它并没有物理实体与之对应。有效端口好从0~65535,其中0~1024是系统保留的。一些常用程序的默认端口:浏览器80端口,TomCat服务器8080端口,MySQL3306端口
传输协议:即传输协议,国际组织定义的通用协议是TCP/IPTCP/IP既能用于局域网,也能用于广域网。除了TCP/IP,还有其他的协议,例如UDPFTPHTTP
TCPUDP在传输层。IP协议在网络层。FTP协议、HTTP协议在应用层
数据封包:
数据拆包:
IP地址:

体系结构:

|----InetAddress

|----Inet4Address,

    |----Inet6Address

InetAddress中没有提供构造函数,但它提供了多种静态方法,以获取本类对象

socket地址:

封装的是带端口号的IP地址

|——SocketAddress

        |———InetSocketAddress

eg:
import java.net.*;
class  IPDemo
{
	public static void main(String[] args) throws Exception
	{
/*
 * 		//下边这句话会报未知主机异常
 * 		//获取本地主机IP地址
		InetAddress i= InetAddress.getLocalHost();
		
		System.out.println(i.toString());
		String adr = i.getHostAddress();
		String name = i.getHostName();
		sop("adr="+adr+" name="+name);
*/		
		//获取其他主机IP地址
		//通过主机名获取IP地址,需要解析,所以较慢,而且对于百度、新浪这样的主机名,获得的IP地址可能不唯一。
		InetAddress i= InetAddress.getByName("www.sina.com");
		
		System.out.println(i.toString());
		String adr = i.getHostAddress();//获得IP地址的字符串表现形式
		String name = i.getHostName();//获取主机名
		sop("adr="+adr+" name="+name);


	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}

二.TCP与UDP 区别

UDP:

是面向无连接的,它将数据集源和目的封装成数据包中,不需要建立连接;它的每个数据报(Datagram)的大小限制在64k以内;因为无连接,是不可靠的协议;同样因为不需要建立里连接,所以速度快。

应用特点:只求速度快,数据丢失对程序影响不大。

应用程序实例:聊天室工具、视频、网络会议等


TCP:

需要建立连接,形成传输数据的通道;在连接中进行大量数据传输;通过三次握手协议完成连接,是可靠的协议;因为必须建立连接,所以效率会稍低。(TCP不像UDP需要封包,而且每个包不能超过64k,它可以大量的传输数据)。

应用特点:适合对数据完整性要求高的程序。

应用程序实例:下载程序

SOCKET:

网络编程其实就Socket编程,Socket是为网络服务的一种机制。(Socket,中文意思为插座)

通信的两端都有Socket,网络通信其实就是Socket间的通信,数据在两个Socket间通过IO传输

UDP传输:

UDP两端是发送端接受端

DatagramSocket:UDP传输专用的程序通信端点,既能发送也能接受

DatagramSocket:数据报包,封装了UDP传输的数据报。里边可以设置要发送的目的地IP地址、端口及要发送的数据

eg:

/*
需求:通过Udp传输方式,将一段文字数据发送出去。
定义一个udp发送端。
思路:
1。建立UDPsocket服务。
2.提供数据,并将数据封装到数据包中。
3.通过socket服务的发送功能,将数据包发出去。
4.关闭资源。
*/
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 i coming!".getBytes();
		DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.13"),10000);
		//3.通过socket服务,将已有的数据包发送出去,通过send方法。	
		ds.send(dp);
		//4.关闭资源。它使用了底层的资源,所以要关闭资源。
		ds.close();

	}
}
/*
需求;
定义一个应用程序,用于接收并处理数据。

定义udp接受端
思路:
1.定义socket服务,通常会监听一个端口,其实就是给这个接受网络应用程序定义一个数字标示。
	方便与明确哪些数据过来该应用程序可以处理。
2.定义一个数据包,因为要存储要接受到的字节数据,
因为数据包对象中有更多功能可以提取字节数据中的不同数据信息。
3.通过socket服务的receive方法将收到的数据存入已定义的数据包中。
4.通过数据包对象的特有功能,将这些不同的数据取出,打印在控制台上。
5.关闭资源。
*/
class UdpRece
{
	public static void main(String[] args) throws Exception
	{
		//1.创建udpsocket,建立端点。这里必须定义监听的端口,其实就是给网络应用程序定义数字标识。
		DatagramSocket ds = new DatagramSocket(10000);
		//2.定义数据包,用于存储数据。
		byte [] buf = new byte[1024];		
		DatagramPacket dp = new DatagramPacket(buf,buf.length);
		//3.通过服务的receive方法,将收到的数据存入到数据包中。	
		ds.receive(dp);//receive是一个阻塞式方法没有接受到数据,会一直等待
		//4.获取数据包中的方法获取其中的数据。
		InetAddress  i= dp.getAddress();
		String ip = i.getHostAddress();
		String  data = new String(dp.getData(),0,dp.getLength());
		int port = dp.getPort();
		System.out.println(ip+"::"+data+"::"+port);
		//5、关闭资源
		ds.close();
	}
}
 

eg:

import java.io.*;
class  UdpSend2
{
	public static void main(String[] args) throws Exception
	{
		DatagramSocket dg = new DatagramSocket(18000);
		//读取键盘录入
		BufferedReader bufr =
			new BufferedReader(new InputStreamReader(System.in));

		String line = null;
		//192.168.1.255是这个网段的广播地址,用它就能实现局域网群聊。
		InetAddress ip = InetAddress.getByName("192.168.1.255");
		DatagramPacket dp = null; 
		while((line=bufr.readLine())!=null)
		{
			if("over".equals(line))
				break;
			byte [] buf = ("sender:"+line).getBytes();
			dp = new DatagramPacket(buf,0,buf.length,ip,17000);
			dg.send(dp);
		}
		dg.close();
		
	}
}

class  UdpRece2
{
	public static void main(String[] args) throws Exception
	{
		DatagramSocket dg = new DatagramSocket(17000);
		byte[] buf = new byte[1024];
		DatagramPacket dp = new DatagramPacket(buf,buf.length);
		while(true)
		{
			dg.receive(dp);
			String ip = dp.getAddress().getHostAddress();
			String data = new String(dp.getData(),0,dp.getLength());
			System.out.println("("+ip+":"+dp.getPort()+")"+data);
			//System.out.println(new String(buf,0,dp.getLength()));
		}
	}
}

UDP 聊天程序

eg:

/*
编写一个聊天程序
有接受数据的部分,和发数据的部分。
这两部分需要同时执行。那就需要用到多线程技术。
一个线程控制收,一个线程控制发。

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

*/
import java.net.*;
import java.io.*;
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)
			{
				if("886".equals(line))
					break;
				byte[] buf =line.getBytes();
				//把发送地址,设为广播地址,
				InetAddress i = InetAddress.getByName("192.168.1.255");				
				DatagramPacket dp=
					new DatagramPacket(buf,0,buf.length,i,10020);
				ds.send(dp);
			}
			ds.close();
			
		}
		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());
				System.out.println("ip:"+ip+" data:"+data);
			}
		}
		catch (Exception e)
		{
			throw new RuntimeException("接受端失败");
		}

	}
}
class  ChatDemo
{
	public static void main(String[] args) throws Exception
	{
		DatagramSocket sendSoket = new DatagramSocket();
		DatagramSocket receSoket = new DatagramSocket(10020);

		new Thread(new Send(sendSoket)).start();
		new Thread(new Rece(receSoket)).start();
		
	}
}









------- android培训java培训、期待与您交流! ----------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值