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

java 网络编程之UDP通信和简单的群聊程序

2018-01-08 23:08 696 查看
UDP通信需要明确的几点:

UDP通信不是面向连接的,发送端不管接收端是否启动是否能接收,发完数据报就结束。

无论是发送端还是接收端,都需要描述两个对象:套接字和数据报。

接收端的套接字对象中必须明确接收端口,且必须和发送端指定的目标端口一致。而发送端的套接字中则一般采用随机分配的发送端口。

无论是发送端还是接收端,数据报中都记录了自己和对方的socket信息(ip+port),还提供了用于发送或接收的数据缓冲区。这些数据只有数据报对象自己最清楚,如
getPort()
,
getAddress()
,
getData()
等。

(1).只不过对于发送端来说,创建发送报文对象需要指定目标套接字信息(ip+port),还需明确数据发送缓冲区。

(2).而对于接收端来说,则只需明确一个数据接收缓冲区即可。

接收端应该不断循环地负责接收。

UDP套接字类DatagramSocket,UDP数据报类DatagramPacket。

UDPSender端:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

public class UDPSender {

public static void main(String[] args) {
DatagramSocket dgs = null;
try {
// 1. 创建udp发送端的socket,一般使用随机发送端口
dgs = new DatagramSocket();

// 2. 创建udp报文包对象
// 2.1 创建数据发送缓冲区
String text = "Hello World! I'm coming";
byte[] buf = text.getBytes();

// 2.2 创建发送数据报文对象
InetSocketAddress isa = new InetSocketAddress("192.168.0.124",8888);
DatagramPacket dgp = new DatagramPacket(buf,buf.length,isa);
//DatagramPacket dgp = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.0.124"), 8888);

// 3.发送udp报文
dgs.send(dgp);

} catch (SocketException e1) {
e1.printStackTrace();
} catch (UnknownHostException e2) {
e2.printStackTrace();
} catch (IOException e3) {
e3.printStackTrace();
} finally {
// 4. 关闭套接字
dgs.close();
}
}
}

UDPRecver端:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class UDPRecver {

public static void main(String[] args) {
while(true){
// 1.创建udp接收套接字,接收端必须指定正确的端口
DatagramSocket dgs = null;
try {
dgs = new DatagramSocket(8888);

// 2. 创建udp接收数据包对象
byte[] buf = new byte[1024];
DatagramPacket dgp = new DatagramPacket(buf, buf.length);

// 3.从套接字中接收数据到数据包中
dgs.receive(dgp);

// 4.展示udp发送端相关信息,包括发送的数据
String data = new String(dgp.getData(), 0, dgp.getLength());
String ip = dgp.getAddress().getHostAddress();
int port = dgp.getPort();
System.out.println("Data: "+data+"   ip: "+ip+"   port: "+port);
} catch (SocketException s) {
s.printStackTrace();
} catch (IOException i) {
i.printStackTrace();
} finally {
dgs.close();
}
}
}
}

UDP实现群聊:

思路:

一个线程负责发,一个线程负责收,因此使用多线程。

发送端的数据报目标端应该指定为广播目标。且发送的数据来源于键盘输入。

接收端要无限循环接收数据,但应该提供下线离开功能。(假设收到了"bye",就表示下线)

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;

public class QunChat {
public static void main(String[] args) throws SocketException {
//发送端和接收端套接字,接收端套接字端口为8888,需要传递给发送端的报文对象
DatagramSocket send_socket = new DatagramSocket();
DatagramSocket recv_socket = new DatagramSocket(8888);

Sender sender = new Sender(send_socket,8888);
Recver recver = new Recver(recv_socket);

Thread send_thread1 = new Thread(sender);
Thread recv_thread1 = new Thread(recver);
send_thread1.start();
recv_thread1.start();
}
}

class Sender implements Runnable {
private DatagramSocket send_sock;
private int dest_port;
Sender(DatagramSocket s,int port){  //初始化时就指定目标端口
this.send_sock = s;
this.dest_port = port;
}

public void run() {
while(true) {
try {
//群聊发送目标,以广播为例
InetSocketAddress isa = new InetSocketAddress("192.168.0.255", dest_port);
//从键盘接收数据
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
String line;
while((line=bufr.readLine())!=null) {
//如果发送的是bye,则断开,且不发送给接收端
if(line.equals("bye")) break;

byte[] buf = line.getBytes();
DatagramPacket dp = new DatagramPacket(buf,buf.length, isa);
send_sock.send(dp);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
send_sock.close();
}
}
}
}

class Recver implements Runnable {
private DatagramSocket recv_sock;
Recver(DatagramSocket socket){
this.recv_sock = socket;
}

public void run() {
while(true) {
try {
//接收报文对象
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
recv_sock.receive(dp);
String src_ip = dp.getAddress().getHostAddress();
String data = new String(dp.getData(),0,dp.getLength());
if(data.equals("bye")) System.out.println(src_ip +" leaving");;
System.out.println("Recviving data: "+ data+" from "+src_ip );
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

注:若您觉得这篇文章还不错请点击右下角推荐,您的支持能激发作者更大的写作热情,非常感谢!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: