通过QQ这个软件让我知道,QQ聊天就是通过IP地址、端口号和UDP传输协议,一方在发送信息,一方在接收信息。所以编写UDP山寨QQ聊天,就要了解IP地址、端口号和UDP传输协议。
一、IP地址
a、它是网络中的设备标识
b、不易记忆,可用主机名表示,两者存在映射关系
c、本机回环地址:127.0.0.1,主机名为:localhost。
IP地址:java中对应的是InetAddress类,存在于java.net包中。
二、端口号
a、用于标识进程的逻辑地址,不用进程的标识。
b、有效端口:0 ~65535,系统使用或保留的端口是:0~ 1024。
三、UDP传输协议
1、协议特点:
a、面向无连接,即将数据及源和目的封装成数据包中,不建立链接的发送
b、每个数据包的大小限制在64K之内
c、因无连接,是不可靠的协议
d、不建立连接,速度快。
2、方法:
1)创建 UDPSocket发送服务对象:
DatagramSocket(),不指定端口。DatagramSocket(int port),指定端口。
2)发送:void send(DatagramPacket p)
3)接收:void receive(DatagramPacket p)
其中DatagramPacket:数据报包用来实现无连接包投递服务的,每条报文仅根据该包中包含的信息从一台机器路由到另一台机器中。凡是带地址(InetAddress)的都是用于发送包的。
山寨QQ的代码如下:
import java.io.*;
import java.net.*;
class Send implements Runnable
{
private DatagramSocket ds;
public Send(DatagramSocket ds)
{
this.ds=ds;
}
//复写run方法
public void run()
{
try
{
//键盘输入的数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line=null;
while((line=br.readLine())!=null)
{
//如果输入的数据是"888"就结束聊天
if("888".equals(line))
{
break;
}
byte[] by =line.getBytes();
//将从键盘输入的数据封装成包
DatagramPacket dp =
new DatagramPacket(by,by.length,InetAddress.getByName("192.168.1.116"),10006);
//发送数据
ds.send(dp);
}
}
catch (Exception e)
{
throw new RuntimeException("发送端失败");
}
}
}
class Receive implements Runnable
{
private DatagramSocket ds;
public Receive(DatagramSocket ds)
{
this.ds=ds;
}
public void run()
{
try
{
while(true)
{
byte[] by=new byte[1024];
DatagramPacket dp=new DatagramPacket(by,by.length);
//接收数据
ds.receive(dp);
//获取发送端主机的IP地址
String ip=dp.getAddress().getHostAddress();
//获取接收到的数据
String data=new String(dp.getData(),0,dp.getLength());
//将获取到的发送端主机的IP地址和数据打印在控制台上
System.out.println(ip+"::::::"+data);
}
}
catch (Exception e)
{
throw new RuntimeException("接收端失败");
}
}
}
class CharDemo
{
public static void main(String[] args) throws Exception
{
//通过DatagramSocket的对象创建UDP服务
DatagramSocket sendSocket = new DatagramSocket();
//创建UDP服务,创建与发送相关的端口
DatagramSocket receiveSocket = new DatagramSocket(10003);
Send s = new Send(sendSocket);
Receive r= new Receive(receiveSocket);
//创建线程
Thread t = new Thread(s);
Thread th=new Thread(r);
//开启线程
t.start();
th.start();
}
}