网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket。Socket通常用来实现客户方和服务方的连接。
在java环境下常说的socket编程是指基于TCP/IP协议的网络编程。本篇文章中主要对在最近工作中用到的基于另一协议UDP的socket编程进行简单的说明:
因为基于UDP协议的数据传输不需要向TCP/IP进行三次握手,以丢包的危险换来网络流量的节省,在对包的丢失率要求不高、网络环境较好的情况下可以采用
这一方式。
UDP通信中常用的两个类是:包java.net中提供了两个类DatagramSocket和DatagramPacket用来支持数据报通信,DatagramSocket用于在程序之间建立传送数据报的通信连接, DatagramPacket则用来表示一个数据报。
DatagramSocket的构造方法:
DatagramSocket();
DatagramSocket(int prot);
DatagramSocket(int port, InetAddress laddr)
其中,port指明socket所使用的端口号,如果未指明端口号,则把socket连接到 本地主机上一个可用的端口。laddr指明一个可用的本地地址。给出端口号时要保证不发生端口冲突,否则会生成SocketException类例外。注 意:上述的两个构造方法都声明抛弃非运行时例外SocketException,程序中必须进行处理,或者捕获、或者声明抛弃。
DatagramPacket的构造方法 :
DatagramPacket(byte buf[],intlength);
DatagramPacket(byte buf[], int length, InetAddressaddr, int port);
DatagramPacket(byte[] buf, int offset, int length);
DatagramPacket(byte[] buf, int offset, int length,InetAddress address, int port);
其中,buf中存放数据报数据,length为数据报中数据的长度,addr和port旨明目的地址,offset指明了数据报的位移量。
在接收数据前,应该采用上面的第一种方法生成一个DatagramPacket对象,给出接收数据的缓冲区及其长度。然后调用DatagramSocket 的方法receive()等待数据报的到来,receive()将一直等待,直到收到一个数据报为止。
DatagramPacket packet=new DatagramPacket(buf, 256);
Socket.receive (packet);
发送数据前,也要先生成一个新的DatagramPacket对象,这时要使用上面的第二种 构造方法,在给出存放发送数据的缓冲区的同时,还要给出完整的目的地址,包括IP地址和端口号。发送数据是通过DatagramSocket的方法 send()实现的,send()根据数据报的目的地址来寻径,以传递数据报。
DatagramPacket packet=new DatagramPacket(buf, length,address, port);
Socket.send(packet);
在构造数据报时,要给出InetAddress类参数。类InetAddress在包java.net中定义,用来表示一个Internet地址,我们可 以通过它提供的类方法getByName()从一个表示主机名的字符串获取该主机的IP地址,然后再获取相应的地址信息。
服务器端:
客户端public class UdpServerThread extends Thread { private DatagramSocket ServerSocket; private DatagramPacket packet; private InetAddress serverAddress; private int port; public UdpServerThread(int port, InetAddress serverAddress) { super("UdpServerThread"); newSocket(port, serverAddress); } public void run() { while (!getServerSocket().isClosed()) { StringBuffer sb = new StringBuffer(); try { InetAddress address; int port; byte[] data = new byte[256]; setPacket(new DatagramPacket(data, data.length)); getServerSocket().receive(getPacket()); address = getPacket().getAddress();//获取客户端IP port = getPacket().getPort();//获取客户端Port //将byte型数组转化为string型输出 for (int i = 0; i < data.length; i++) { if (data[i] == 0) { break; } sb.append((char) data[i]); } //此处添加处理数据的操作 } catch (Exception e) { //异常处理 } } }
public void closeSocket() { ServerSocket.close(); } public void startSocket(int port, InetAddress serverAddress) { newSocket(port, serverAddress); } private void newSocket(int port, InetAddress serverAddress) { try { ServerSocket = new DatagramSocket(6000, serverAddress); } catch (SocketException e) { System.out.println(e.getMessage()); System.exit(1); } }}
public static void main(String[] args) { String sendcontent = "要发送的内容"; try { DatagramSocket clientSocket = new DatagramSocket(8000);// 这里的8000是客户端的Port,服务器回复的时候发送到该端口 // 也可以不知道,系统随机分配 DatagramPacket sendPacket = new DatagramPacket(sendcontent .getBytes(), sendcontent.getBytes().length, InetAddress .getByName("127.0.0.1"), 7000);// clientSocket.send(sendPacket); while (!clientSocket.isClosed()) { //此处参考服务器接受packet代码 //实现server和client的通信,这也体现了udp协议通信不分server和client } } catch (SocketException e) { e.printStackTrace(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
代码不是很详细,目的提供一个思路,多包涵