java udp聊天_Java UDP实现聊天功能代码

本文介绍了如何使用Java的UDP编程实现简单的聊天功能。通过DatagramPacket和DatagramSocket类,分别阐述了数据包的发送和接收过程,并提供了Send_Thread、Receive_Thread、Chat_Client和Chat_Server四个类的示例代码,展示了如何创建UDP客户端和服务器端进行交互。
摘要由CSDN通过智能技术生成

我以前经常写的是基于TCP的网络编程,由于TCP建立连接鼻血要经过三次握手连接,服务器端需要阻塞式等待客户端的连接。而UDP则是可以直接向目的地址的目的端口上发送数据包,由于它只负责发送出去就好,不管对方是否正确接受到与否,所以当网络性能不好时它容易出现丢包的问题。(注意:UDP是基于数据报为单位进行传输的,而TCP是一种基于流进行传输的)

但是UDP很好的模拟了我们呢平时聊天的方式,可以很好的实现连续多次发送和接受,也就是简单的QQ聊天的功能。

现在来简要介绍Java中有关UDP编程相关的类:

一个是DatagramPacket,主要用来将数据字节填充到UDP数据报中,用来解包接受数据的,用来收和发UDP数据报。一个是DatagramSocket主要用来是建立客户端和服务器端,用来接受和发送数据报数据的。

(1)DatagramPacket类

UDP首部向IP首部添加了8个字节,包含了源端口和目标端口,IP首部以后内容的长度和校验和,最多有65507个字节数。UDP所使用的端口和TCP使用的端口不一样的,是一个final类。

对于接受数据,将接受到的数据存储到DatagramPacket,然后从该对象中读取数据。

对于发送数据,将发送的数据先存到DatagramPacket中,然后将该对象发送。

接受数据报构造函数:

DatagramPacket(byte[] buffer,int length)

DatagramPacket(byte[] buffer,int offset,int length)

socket将接受到的数据部分存储到buffer,一般buffer的大小最多定义为8192或者512大小即可

发送数据报构造函数:

由于DatagramPacket将数据填充到UDP数据报中,而数据报需要源端口和目标端口,客户端一般创建的端口是匿名的,会在填充的过程中自动的加上,而源端口必须要首先显式的在    DatagramPacket中设置,这样才能填充到UDP数据报中。发送数据都必须要把数据以字节形式发送。以API 1.6

DatagramPacket(byte[] buffer,int length,InetAddress dest,int port)

DatagramPacket(byte[] buffer,int offset,int length,InetAddress dest,int port)

DatagramPacket(byte[] buffer,int length,SocketAddress dest)

DatagramPacket(byte[] buffer,int offset,int length,SocketAddress dest)

注意:SocketAddress是一个抽象类,主要保存了主机名、IP和端口号,

一般可以SocketAddress address=new InetSocketAddress("www.baidu.com",2000)

InetAddress只是用来保存主机名和IP的。

InetAddress getAddress()、getPort()获取发送数据目标地址、端口和接受到数据的源地址、端口

SocketAddress getSocketAddress()(最常用的)一样的意思。

利用getData()获取接受到的数据报数据的字节数组,一般利用

String res=new String(packet.getData(),"ASCII")或

String s=new String(packet.getData(),packet.getOffset(),packet.getLength(),"UTF-8");

获取数据。getLength()返回UDP中数据的字节数。getOffset()数据报中数据开始的点。

对于已经构造好的DatagramPacket,可以在发送之前更改它的一些状态。修改数据报的属性,一般是先创建一个接受数据报的构造函数,然后对其报进行更改属性。

setData(byte[] data)

setData(byte[] data,int offset,int length) 可以用来连续发送大量的数据块

setAddress(InetAddress remote)

setPort(int port)

setAddress(SocketAddress remote)相当于上面两个方法。可以利用这些方法来设置一个数据报发送不同的ip和端口。

setLength(int length)设置包的长度,主要是指定缓冲区中将要发送的字节数,或用来将要接收数据的包数据缓冲区的字节数。

(2)DatagramSocket类

在UDP中没有明显的客户端类和服务器端类,客户端既可以发消息也可以接受消息。均在创建的过程会有SocketException异常。创建UDP客户端构造器

DatagramSocket();创建一个对于客户端来说匿名的端口,发送UDP的过程会自动加上该端口号,服务器接受消息也会按照该端口号发送。

创建UDP服务器构造器

DatagramSocket(int port)

DatagramSocket(int port,InetAddress interface);用于一个主机有多个网络接口的时候

DatagramSocket(SocketAddress interface)

发送数据报

直接调用send(DatagramPacket dp),异常有IOException

接受数据报

receive(DatagramPacket dp);异常有IOException

从网络中接受一个UDP数据报,存储在某一个DatagramPacket。在数据未到达之前会一直阻塞后面的运行,一般在无限循环中接受。

管理连接

connect(InetAddress host,int port)来设置其只对指定的远程主机和指定远程的接受和发送包

getPort()、getInetAddress()返回其连接的远程主机。一般在接受到消息后,需要调用

packet.getSocketAddress(),获取远程主机基本信息

以下是我写的简单的一个聊天程序:

Send_Thread.java

packageChat_UDP;importjava.io.IOException;importjava.net.DatagramPacket;importjava.net.DatagramSocket;importjava.net.InetAddress;importjava.net.InetSocketAddress;importjava.util.Scanner;public class Send_Thread extendsThread{//发送的socket端

private DatagramSocket sender = null;//待发送的目标地址

private InetSocketAddress address = null;//从键盘输入

Scanner scan = newScanner(System.in);publicSend_Thread(DatagramSocket sender,InetSocketAddress address)

{this.sender =sender;this.address =address;

}

@Overridepublic voidrun() {//TODO Auto-generated method stub

try{while(true)

{//输入待发送的内容

String input =scan.nextLine();if(input.equals("exit"))break;byte[] data = null;

data= input.getBytes("UTF-8");//创建UDP数据报

DatagramPacket pack = newDatagramPacket(data, data.length,address);

sender.send(pack);

}

System.out.println("Exit!");

}catch(IOException e)

{

System.out.println("IOException");

}

}

}

Receive_Thread.java

packageChat_UDP;importjava.io.IOException;importjava.net.DatagramPacket;importjava.net.DatagramSocket;public class Receive_Thread extendsThread {private static final int MAX_RECEIVE_BUFFER = 1024;privateDatagramSocket server;privateDatagramPacket packet;byte[] buffer = new byte[MAX_RECEIVE_BUFFER];publicReceive_Thread(DatagramSocket server)

{this.server =server;

packet= newDatagramPacket(buffer, buffer.length);

}

@Overridepublic voidrun() {//TODO Auto-generated method stub

try{while(true)

{//接收数据包

server.receive(packet);

String s= new String(packet.getData(),packet.getOffset(),packet.getLength(),"UTF-8");

System.out.println(packet.getAddress()+" at port "+packet.getPort()+" Says :"+s);

packet.setLength(buffer.length);

}

}catch(IOException e)

{

System.out.println("IOException");

}

}

}

Chat_Client.java

1 packageChat_UDP;2

3 importjava.net.DatagramSocket;4 importjava.net.InetSocketAddress;5

6 public classChat_Client {7

8 private static final int DEST_PORT = 9000;9 private static final int SEND_PORT = 10000;10 private static final int RECE_PORT = 8888;11 private static final String IP = "127.0.0.1";12

13 public static voidmain(String[] args)14 {15 try{16 Send_Thread send_thread = null;17 Receive_Thread rece_thread = null;18 InetSocketAddress address = null;19 //创建待接受数据包的目的机的端口号和IP地址

20 address = newInetSocketAddress(IP, DEST_PORT);21 //创建发送的Socket端

22 DatagramSocket sendsocket = newDatagramSocket(SEND_PORT);23 //创建接受的Socket端

24 DatagramSocket recesocket = newDatagramSocket(RECE_PORT);25 //发送线程建立

26 send_thread = newSend_Thread(sendsocket, address);27 //接受线程的建立

28 rece_thread = newReceive_Thread(recesocket);29

30 send_thread.start();31 rece_thread.start();32

33 }catch(Exception e)34 {35 System.out.println("Exception!");36 }37

38 }39

40

41 }

Chat_Server.java

1 packageChat_UDP;2

3 importjava.net.DatagramSocket;4 importjava.net.InetSocketAddress;5

6 public classChat_Server {7

8 private static final int DEST_PORT = 8888;9 private static final int SEND_PORT = 10001;10 private static final int RECE_PORT = 9000;11 private static final String IP = "127.0.0.1";12

13 public static voidmain(String[] args)14 {15 try{16 Send_Thread send_thread = null;17 Receive_Thread rece_thread = null;18 InetSocketAddress address = null;19 //创建待接受数据包的目的机的端口号和IP地址

20 address = newInetSocketAddress(IP, DEST_PORT);21 //创建发送的Socket端

22 DatagramSocket sendsocket = newDatagramSocket(SEND_PORT);23 //创建接受的Socket端

24 DatagramSocket recesocket = newDatagramSocket(RECE_PORT);25 //发送线程建立

26 send_thread = newSend_Thread(sendsocket, address);27 //接受线程的建立

28 rece_thread = newReceive_Thread(recesocket);29 send_thread.start();30 rece_thread.start();31 }catch(Exception e)32 {33 System.out.println("Exception!");34 }35

36 }37

38 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值