网络编程服务器端接受数据比对不匹配的问题:
在网络编程中我们通常会用到验证用户输入或者文件的情况,在这个时候可能会遇到即使文本正确也比对失败的问题,如这次我做的一个一个简单的发送消息小程序(利用UDP实现)。
需求分析:
一:搭建好网络编程的框架(C/S模型)
二:在客户端接收客户输入,使用DatagramPacket,并通过send方法发送。
三:服务器接收文件,在使用DatagramPacket的receive读取文件后判断数据是否是字符串886。
项目开始:
客户端:
//Client端
public static void main(String[] args) throws IOException {
//创建数据包套接字对象
DatagramSocket ds=new DatagramSocket();
//创建Scanner对象
Scanner sc=new Scanner(System.in);
int flag=0;
//设置标志位,当标志位为0时持续接收消息,当标志位为1时退出循环
while (flag==0){
String s = sc.nextLine();
//如果消息为886,发送消息、关闭数据包并将标志位设为1
if (s.equals("886")){
flag=1;
}
byte[] buf=s.getBytes();
DatagramPacket dp=new DatagramPacket(buf,buf.length, InetAddress.getByName("172.20.20.17"),10000);
ds.send(dp);
}
ds.close();
}
服务器端:
public static void main(String[] args) throws IOException {
boolean flag=true;
//创建数据包套接字对象
DatagramSocket ds=new DatagramSocket(10000);
//设置标志位,当标志位为true时持续接收消息,当标志位为false时退出循环
while (flag){
byte[] buf =new byte[1024];
DatagramPacket dp=new DatagramPacket(buf,buf.length);
//接收数据包
ds.receive(dp);
//解析数据包
String s=new String(dp.getData());
System.out.println(s);
//如果数据为886退出循环
if ("886".equals(s))
{
flag=false;
}
}
ds.close();
}
但是在运行结束后发现,及时发送了886,服务器端也没有跳出接收循环。Debug后发现运行到判断语句后直接略过并没有执行将标志位归为的操作。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nIGAphf2-1618282608022)(C:\Users\asus\AppData\Roaming\Typora\typora-user-images\image-20210412152019519.png)]
后期研究API发现,这是由于String的底层是字符数组,当用字符数据buf创建并设置其长度为1024时,用
String s=new String(dp.getData());
来直接将其转为为String对象,会把所有超长的字符空间置为null,此时再用
"886".equals(s)
去判断,则会判断失败。最后通过查看API文档了解到有
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A1bvPUxc-1618282608024)(C:\Users\asus\AppData\Roaming\Typora\typora-user-images\image-20210412152929084.png)]
这个构造方法,可以通过设置偏移量和长度来避免这个问题,于是服务器端最后修改成这个样子。
public static void main(String[] args) throws IOException {
boolean flag=true;
//创建数据包套接字对象
DatagramSocket ds=new DatagramSocket(10000);
//设置标志位,当标志位为true时持续接收消息,当标志位为false时退出循环
while (flag){
byte[] buf =new byte[1024];
DatagramPacket dp=new DatagramPacket(buf,buf.length);
//接收数据包
ds.receive(dp);
//解析数据包
String s=new String(dp.getData(),0,dp.getLength());
System.out.println(s);
//如果数据为886退出循环
if ("886".equals(s))
{
flag=false;
}
}
ds.close();
}
if ("886".equals(s))
{
flag=false;
}
}
ds.close();
}