UDP初步
作者:Legend
QQ:158067568
使用UDP协议进行信息的传输之前不需要建议连接。换句话说就是客户端向服务器发送信息,客户端只需要给出服务器的ip地址和端口号,然后将信息封装到一个待发送的报文中并且发送出去。至于服务器端是否存在,或者能否收到该报文,客户端根本不用管。
明白了上一段的内容对使用udp协议进行编程十分有用。在最开始学java时,我总是追求别写速度快,想象自己能构想电影里的黑客一样,在电脑面前快速敲击键盘,然后很快就能写出超赞的程序。所以盲目的追求API的使用熟练,忘记了语言的精髓不是语法的纯熟,而在于真正有价值的是你要说什么。说什么有意义,有深度,只有明白了这样,才能继续往深处走。以为的追求api的使用没有丝毫的价值。
简单UDP连接
从最简单的内容开始,首先要建立一个简单的udp连接,大致要实现的内容如下:
首先编写服务器端,服务器监听一个端口,然后一直阻塞等待客户端发来的消息。客户端向服务器端的这个端口发送一个数据报,此时服务器端将接受的该数据报,然后打印出来。
首先实现服务器端,对于服务器端,他不需要知道是谁发送给他的数据就能接受到数据报。但是服务器端必须要制定一个端口,不然客户端将不知道发送到服务器端的那个端口。代码如下:
package cn.edu.zcl.udp.unicast;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class UDPUnicastServer {
/**
* @param args
* @throws SocketException
*/
public static void main(String[] args) throws SocketException {
DatagramSocket clientDSocket ;
DatagramPacket receiveDP = new DatagramPacket(new byte[1024], 1024);
clientDSocket = new DatagramSocket(9998);
try {
clientDSocket.receive(receiveDP);
System.out.println(receiveDP.getAddress()+" "+receiveDP.getPort());
} catch (IOException e) {
e.printStackTrace();
}
}
}
接下来是客户端,客户端首先需要知道服务器端的ip地址和端口号,然后把要发送的信息连同数据报一起封装,这样客户端才知道把数据报发送到哪个地方。之后通过DatagramSocket的send方法就可以将封装好的数据报发送出去。具体代码如下:
package cn.edu.zcl.udp.unicast;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class UDPUnicastClient {
/**
* @param args
* @throws SocketException
*/
public static void main(String[] args) throws Exception {
DatagramSocket clientDSocket ;
DatagramPacket sendDP =
new DatagramPacket(new byte[1024], 1024,InetAddress.getByName("localhost"),9998);
clientDSocket = new DatagramSocket(9199);
try {
clientDSocket.send(sendDP);
} catch (IOException e) {
e.printStackTrace();
}
}
}
以上是最简单的udp通讯的一个模型,代码可以在代码包中找到。接下来将介绍如何将数据封装在数据报中发送出去。接下来的代码只是对上面的代码进行简单的修改:udp协议传输的是byte数组,所以对于字符串,只要将字符串信息转换成byte数组就可以了,执行String类的getBytes()方法就可实现以上操作。而在服务器端只要通过数据包的getData()方法就可以接收到该byte数组。这部分代码的改动不大,读者可以参考UDPUnicastSendDataClient与UDPUnicastSendDataServer代码。
UDP不同类型数据的传输
问题接种而来,字符串的类中提供了转换成byte数组的方法,但是对于int型、float型、double….应该如何操作呢?
对对于这部分知识,如果对计算机组成原理等相关课程学得好的同学,应该是小菜一碟。byte(字节)是8用8bit(二进制位)来表示的,而整数类型是由32bit来表示。如果要用byte来表示int的话,就需要4个byte才可以。我是这样设计的,首先在byte[0]中,存储int的最低八位,然后byte[1]中存储int的次低八位,依次类推,这样就可以将int存储在byte中了。当读取时采用相反操作就ok了。以下是代码。
package cn.edu.zcl.util.bytearray;
import java.io.IOException;
/**
* 该类实现不同数据类型与byte数组之间的转换
* @author Legend
*
*/
public class ByteArrayUtil {
/**
* 将指定的int数组转换为byte[]数组
* @param i 指定待转换的int类型变量
* @return 返回转换后的byte数组
* @throws IOException
*/
public static byte[] toByteArrayFromInt(int i) throws IOException {
byte[] b= new byte[4];
b[0] = (byte)i;
b[1] = (byte)(i>>8);
b[2] = (byte)(i>>16);
b[3] = (byte)(i>>24);
return b ;
}
/**
* 将指定的byte字节数组转换成int类型数据
* @param byteArray 待转换数组
* @return 转换后的
* @throws IOException
*/
public static int toIntFromByteArray(byte[] byteArray) throws IOException {
int result = 0;
result = (int)(byteArray[0]|byteArray[1]<< 8 | byteArray[2] << 16 | byteArray[3] << 24);
return result;
}
public static void main(String[] args) throws IOException{
byte[] b =toByteArrayFromInt(22);
int i = toIntFromByteArray(b);
System.out.println(i);
}
}
对于以上代码在文件ByteArrayUtil.java中。
对于其他类型转换,暂时先不在做讲解,读者可以自行百度,如果后有时间,我会将这部分的内容补充完整。
刚开始没有注意,博文写完之后才发现,所有的类中的没有添加套接字关闭的动作,不过源代码已将上次,就不在修改了。