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

[学习笔记]Java网络编程之UDP通讯

2014-12-21 16:15 726 查看


计算机网络体系结构


1.体系结构

计算机网络各层及其协议的集合,称为网络的体系结构。目前公认的计算机网络体系结构有概念清楚理论完善的OSI七层协议结构和实际上广泛应用的TCP/IP四层体系结构。






2.各层概述

应用层:直接为用户的程序提供服务,如支持万维网应用的HTTP协议,支持电子邮件的SMTP协议等。
运输层:负责向两个主机中进程之间的通信提供服务,主要使用面向连接的TCP协议和无连接的UDP协议。
网络层:负责为分组交换网上不同主机提供地址交付的通信服务,该层使用IP协议,所以在该层传送的数据称之为IP数据报。路由器工作在该层。
数据链路层:负责将IP数据报在相邻的节点之间传输,该层将IP数据报封装成帧,将IP地址转换为MAC硬件地址封装在帧中进行节点间的传输。网桥,桥接器和交换机都工作在该层。
物理层:包括数据传输的介质和电气特性,包括电缆,光缆,光信号,电信号的标准等。转发器,信号放大器都工作在该层。
每一层的实际运作对上一层都是透明的。
应用程序间通过网络交换数据,数据在发送方从上到下层层封装,通过物理层传输,到接收方又从下至上层层拆封还原原始数据。


Java中的网络通讯


1.IP地址


1.1概述

IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。


1.2域名解析

为了方便记忆,出现域名,并且需要从域名转化为IP地址的协议或服务,该服务就是域名解析(DNS)。

特殊地址

127.0.0.1:本机回环地址。
主机号为全1:该网络广播地址。

1.3InetAddress类


概述

该类没有构造器。
该类用于IP地址的封装。

方法

返回本机IP原始地址

byte[]getAddress()
通过主机名或IP地址获取IP地址对象

staticInetAddress[]getAllByName(Stringhost)

staticInetAddressgetByAddress(byte[]addr)

staticInetAddressgetByAddress(Stringhost,byte[]addr)

staticInetAddressgetByName(Stringhost)
获取主机IP地址或主机名
staticInetAddressgetLocalHost()

StringgetHostAddress()

StringgetHostName()


示例

packagenet;
importjava.net.InetAddress;
importjava.net.UnknownHostException;
publicclassInetDemo{
publicstaticvoidmain(String[]args)throwsUnknownHostException{
//获取本机IP对象
InetAddressiphost=InetAddress.getLocalHost();
Stringipstr=iphost.getHostAddress();//"192.168.1.22"
Stringipname=iphost.getHostName();//"YH-PC"
//获取指定IP对象
InetAddressip=InetAddress.getByName("192.168.1.1");
ipstr=ip.getHostAddress();//"192.168.1.1"
ipname=ip.getHostName();//"192.168.1.1"
//获取指定主机的IP对象
InetAddress[]ips=InetAddress.getAllByName("www.google.com.hk");
for(inti=0;i<ips.length;i++){
ipstr=ips[i].getHostAddress();
ipname=ips[i].getHostName();
System.out.println(ipstr);
System.out.println(ipname);
//173.194.120.88
//www.google.com.hk
//216.239.32.39
//www.google.com.hk
}
}
}



2.端口号

全称为TCP/IP端口,是应用层用于识别通讯进程的接口。
有效端口:0~65535,系统使用或保留的端口是:0~1024。


3.传输层协议


3.1UDP协议

无连接的,不保证可靠交付,只能提供尽最大努力交付。
无需创建链接,速度较快。
支持一对一,一对多,多对一,多对多通讯。
面向报文的通信。
没有拥塞控制,所以可能会有丢包,但是传输速率不受影响,延时较小,适合实时性要求高的网络视频,聊天等。

3.2TCP协议

面向连接的,提供可靠交付服务。
TCP链接只能有两个端点,所以只能是点对点(一对一)通讯。
TCP提供全双工通信,适合大数据量的传输。
面向字节流的通信。
需要通过三次握手建立链接,速度稍慢。


4.通讯过程

明确IP地址。
明确通讯端口。
明确使用协议。
建立Socket(套接字,类似于通信链接的端口,插口)通信服务。
建立通信数据报文Package。
使用Socket来发送或接收报文。


UDP协议相关API


1.DatagramSocket类


概述

该类用于UDP通讯套接字的建立。


构造器

绑定本地主机创建套接字

DatagramSocket()

DatagramSocket(intport)
绑定指定主机创建套接字(当一台机器拥有多于一个IP地址的时候,由它创建的实例仅仅接收来自指定地址的报文)

DatagramSocket(DatagramSocketImplimpl)

DatagramSocket(intport,InetAddressladdr)

DatagramSocket(SocketAddressbindaddr)

常用方法

将套接字绑定到特定的IP地址和端口号

voidbind(SocketAddressaddr)
关闭该套接字

voidclose()
将该套接字连接至远程地址(用于建立单向通讯)

voidconnect(InetAddressaddress,intport)

voidconnect(SocketAddressaddr)
断开链接

voiddisconnect()
获取与该套接字连接的地址

InetAddressgetInetAddress()

SocketAddressgetRemoteSocketAddress()
获取与该套接字连接的端口号

intgetPort()
获取与该套接字绑定的本地地址

InetAddressgetLocalAddress()

SocketAddressgetLocalSocketAddress()
获取与该套接字绑定的本地端口号

intgetLocalPort()
判断套接字状态

booleanisBound()

booleanisClosed()

booleanisConnected()
接收和发送

voidreceive(DatagramPacketp)

voidsend(DatagramPacketp)
设置接收和发送缓冲区大小以及超时限制

voidsetReceiveBufferSize(intsize)

voidsetSendBufferSize(intsize)

voidsetSoTimeout(inttimeout)

2.DatagramPacket类


概述

该类用于数据报文的建立。


构造器

建立发送报文

DatagramPacket(byte[]buf,intlength,InetAddressaddress,intport)

DatagramPacket(byte[]buf,intoffset,intlength,InetAddressaddress,intport)

DatagramPacket(byte[]buf,intoffset,intlength,SocketAddressaddress)

DatagramPacket(byte[]buf,intlength,SocketAddressaddress)
建立接收报文

DatagramPacket(byte[]buf,intlength)

DatagramPacket(byte[]buf,intoffset,intlength)

常用方法

获取该数据报发送的目的地址或接收的源地址。

InetAddressgetAddress()

SocketAddressgetSocketAddress()

intgetPort()
获取数据报数据长度和偏移量

intgetLength()

intgetOffset()
设置数据报发送地址

voidsetAddress(InetAddressiaddr)

voidsetSocketAddress(SocketAddressaddress)

voidsetPort(intiport)
设置数据报数据

voidsetData(byte[]buf)

voidsetData(byte[]buf,intoffset,intlength)

voidsetLength(intlength)


3.通信步骤


发送端

建立套接字。
明确目标地址和端口号,建立带地址的数据报文。
使用套接字发送数据报文。
关闭套接字。

接收端

明确端口号,建立带端口号套接字。
建立接收的数据报文。
使用套接字接收数据报文。
关闭套接字。


4.示例


UDP发送端

packagenet;
importjava.io.IOException;
importjava.net.DatagramPacket;
importjava.net.DatagramSocket;
importjava.net.InetAddress;
publicclassUDP_Send{
publicstaticvoidmain(String[]args)throwsIOException{
/*
*UDP发送端
*/
System.out.println("UDP发送端");
//获取本地IP地址
InetAddressip=InetAddress.getLocalHost();
System.out.println("DestinationIP="+ip.getHostAddress());
//1.建立UDP的socket
DatagramSocketds=newDatagramSocket();
//2.将数据封装到数据包中
byte[]buf="helloUDP!".getBytes();
DatagramPacketdp=newDatagramPacket(buf,buf.length,ip,22222);
//3.使用Socket对象的send方法将数据包发送出去
ds.send(dp);
//4.关闭资源。
ds.close();
}
}



UDP接收端

packagenet;
importjava.io.IOException;
importjava.net.DatagramPacket;
importjava.net.DatagramSocket;
publicclassUDP_Receive{
publicstaticvoidmain(String[]args)throwsIOException{
/*
*UDP接收端
*/
System.out.println("UDP接收端");
//1.建立UDP的socket
DatagramSocketds=newDatagramSocket(22222);
//2.定义数据包方便接收数据
byte[]buf=newbyte[1024];
DatagramPacketdp=newDatagramPacket(buf,buf.length);
//3.使用Socket对象的receive方法阻塞接收数据
ds.receive(dp);
//4.获取接收到的数据
Stringip=dp.getAddress().getHostAddress();
intport=dp.getPort();
Stringdata=newString(dp.getData(),0,dp.getLength());
System.out.println("ip="+ip+"\nport="+port+"\ndata="+data);
//4.关闭资源。
ds.close();
}
}



实例


聊天室程序

packagenet;
importjava.io.BufferedReader;
importjava.io.IOException;
importjava.io.InputStreamReader;
importjava.net.DatagramPacket;
importjava.net.DatagramSocket;
importjava.net.InetAddress;
importjava.net.SocketException;
importjava.net.UnknownHostException;
publicclassTest_ChatByUDP{
publicstaticvoidmain(String[]args)throwsSocketException,UnknownHostException{
//创建用于发送和接收的套接字,端口33333只用于聊天室接收程序。
DatagramSocketsendDs=newDatagramSocket();
DatagramSocketreceDs=newDatagramSocket(33333);
//创建广播地址
InetAddressip=InetAddress.getByName("192.168.1.255");
//创建发送和接收对象
Sendsd=newSend(sendDs,ip);
Recerc=newRece(receDs);
newThread(sd).start();
newThread(rc).start();
}
}
classSendimplementsRunnable{
privateDatagramSocketds;
privateInetAddressip;
publicSend(DatagramSocketds,InetAddressip){
super();
this.ds=ds;
this.ip=ip;
}
@Override
publicvoidrun(){
//读取键盘录入
BufferedReaderbr=newBufferedReader(newInputStreamReader(System.in));
Stringstr=null;
try{
while((str=br.readLine())!=null){
//发送键盘录入的字符
DatagramPacketdp=newDatagramPacket(str.getBytes(),str.length(),ip,33333);
ds.send(dp);
if("exit".equals(str)){
break;
}elseif("close".equals(str)){
break;
}
}
ds.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
classReceimplementsRunnable{
privateDatagramSocketds;
publicRece(DatagramSocketds){
super();
this.ds=ds;
}
@Override
publicvoidrun(){
while(true){
byte[]buf=newbyte[1024];
DatagramPacketdp=newDatagramPacket(buf,buf.length);
try{
//阻塞接收
ds.receive(dp);
}catch(IOExceptione){
e.printStackTrace();
}
//获取发送方地址
Stringip=dp.getAddress().getHostAddress();
Stringstr=newString(dp.getData(),0,dp.getLength());
intport=dp.getPort();
if("exit".equals(str)){
//判断发送字符
System.out.println(ip+":"+port+"离开了聊天室!");
}elseif("close".equals(str)){
System.out.println(ip+":"+port+"请求关闭聊天室!");
break;
}else{
System.out.println(ip+":"+port+"说:"+str);
}
}
ds.close();
System.out.println("聊天室已关闭!");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: