冰断秋
这是不是因为UDP协议是无连接、不可靠的原因?
chenkaifan
getByte是为了把字符串转换成字节数组,然后才能装进packet进行传输啊
杨勤_cd
你的DatagramSocket socket是主线程的东西,新建的其他线程当然用不了,你把sokect放在公共区用volatile修饰让所有线程共享就可以了,亲测。
代码:
public class UDPServer2 {
public static volatile DatagramSocket socket;//指定服务器端口
static {
try {
socket = new DatagramSocket(8110);
} catch (SocketException e) {
e.printStackTrace();
}
}
public static volatile byte[] data = new byte[1024];
public static volatile DatagramPacket packet = new DatagramPacket(data, data.length);//创建数据报,用于接收客户端发送的数据
public static void main(String[] args) throws IOException {
//接收请求
// DatagramSocket socket = new DatagramSocket(8110);//指定服务器端口
// byte[] data = new byte[1024];
// DatagramPacket packet = new DatagramPacket(data, data.length);//创建数据报,用于接收客户端发送的数据
System.out.println("========服务器已启动,正在等待客户端发送数据======");
while (true) {
socket.receive(packet);//此方法在接收到客户端数据之前会一直阻塞
new Thread(new ThreadUDPServer(socket, packet)).start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Kuneng
我觉得真正对data数组动手脚的应该是receive方法 会不会是返回一个data数组覆盖了前面定义的数组呢?
艾米丽宏


JDK API 中文版,你值得拥有。
幕布斯1117532
把Datagramsocket放到循环外试一下
Datagrampacket packet=new Datagrampacket(new byte[1024],1024);
while(true){
datasocket.receive(packet);
byte[]arr=packet.getData();
int len=packet.length();
syso(arr,0,len);
}
街边七号
将两边同时调整数组大小
次声的爱
是不是发送的packet里没有ip地址?创建发送端的DatagramPacket时要用4参数的
define_ray
可以
finally{
//关闭资源
try {
if (socket!=null)
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
kipu
我把UDP写在了while里 emmmm 不说了 我去换个CUP
慕粉1723059600
List 接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。(此类大致上等同于 Vector 类,除了此类是不同步的。)
所以满了会自己增加容量(数组自动扩容)
慕粉18435131560
确实,可以定义100,1000,但你要确保你发送的数据比你开辟的空间小就好
慕粉4241372
原因:socket.receive(packet)会锁死对象packet,主线程锁死packet对象后,在start()的子线程中不能调用 packet.属性,packet.方法()。
解决办法:
while(true){
byte[] data=new byte[1024];//创建字节数组,指定接受的数据包的大小
DatagramPacket packet=new DatagramPacket(data, data.length);
socket.receive(packet);//此方法在接受到数据之前会一直阻塞
UDPServerThread serverThread=new UDPServerThread(socket,apcket,data);
serverThread.start();
}
这样在while循环到第二次时,new了一个新的packet对象,主线程锁住新对象,上一次的对象自动解锁,上一次循环时新建的子线程中的对packet进行调用的方法才可以开始执行
单行道上
这是线程的使用方面的知识。run()方法里面的叫线程体,是在这个线程需要执行的具体逻辑,而start()方法是启动线程。我们调用start()方法启动这个线程,然后系统会自动调用run()方法去执行里面的逻辑。如果我们不调用start(),而调用run(),的确可以运行run()方法里面的逻辑,但是那是在当前线程执行的,没有新的线程被建立,也就不叫多线程了。你应该补充一下线程方面的基础知识。
进击的猿
因为是客户端连接服务器建立了通信的通道,使客户端和服务器连接起来,所以已经建立好了桥梁,就可以发送信息过来了,而不需要再次连接。
EdSheeran
继承了Thread类,run()方法没有运行。看你是想实现runnable接口,但是却继承了Thread类。只有实现了Runnable接口,run()方法才能自动运行。还有,第二行有两个分号。
服务器端程序(UDPRunnable)没有入口(没有main方法。)
DatagramSocket socket=new DatagramSocket();未指定端口号。
服务器端程序(UDPRunnable)步骤有误。县先创建DatagramSocket实例,指定端口,在创建DatagramPacket数据包,在用socket实例接收数据。玩了用String的构造方法读取数据。客户端代码没有问题。
其他的没有看出来。共同学习,嘻嘻~
疯木木
代码呢?可能服务器端定义变量的时候重名了吧
捞捞
好吧,把socket换成packet就可以了,我对象理解错了
还有服务器端的socket不能关闭
Xtick
无聊吧
应龙
因为这个里面的bytes是有固定长度的,是1024,而读取时,读的最多也是1024光一个bytes的字符串就站满了,所以要修改,sb.append(new String(bytes).trim());这样就好了
Coral_3673831
这个问题好简单啊。无法直接解答
少艾
很简单,上面定义了一个DatagramPacket packet=new DatagramPacket(data,data.length);你就把它想象成空的模型,模子已经搭好了但是没有数据。而socket.receive(packet);这句话就是将这个类似模型结构的值存入到这个模型里面,然后通过这个模型获得其他想要的信息,例如InetAddress address=packet.getAddress();
---------------------------------------------------------------------
老师之前说过了这句话,所有的信息都存储于DatagramPacket 中,所以,UDP是针对于packet进行主要操作的。
带头大哥丧膘
第1,你可能没有导入包
第2,你可能没有实例化这个对象...比如:DatagramPacket packet = null;而不能DatagramPacket packet;这样会报错。
狮子追求真理
仅供参考:
public class UdpSocketMilServerDemo {
public static void main(String[] args) {
DatagramSocket socket = null;
try {
/*
* 接受客户端发送到服务器的数据信息
*/
int count = 0;
//创建DatagramSocket,指定端口
socket = new DatagramSocket(8800);
while(true){
//创建DatagramPacket,用于存储客户端发送的信息
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, data.length);
//接受从客户端发送来的请求信息,并存储在DatagramPacket中
socket.receive(packet);
UdpThread thread = new UdpThread(socket, data, packet);
thread.start();
count++;
System.out.println("总共有"+count+"个用户登录");
}
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
socket.close();
}
}
}
public class UdpThread extends Thread {
private DatagramSocket socket;
private byte[] data;
private DatagramPacket packet;
public UdpThread(DatagramSocket socket,byte[] data,DatagramPacket packet){
this.socket = socket;
this.data = data;
this.packet = packet;
}
@Override
public void run() {
try {
//读取获取到的客户信息
String info = new String(data, 0, packet.getLength());
System.out.println("我是服务端,客户端说:"+info);
/*
* 对客户端的请求进行响应
*/
//获取客户端主机信息和定义要响应的信息
InetAddress address = packet.getAddress();
int port = packet.getPort();
byte[] data2 = "欢迎您!".getBytes();
//定义一个DatagramPaket,用户存放响应信息
DatagramPacket responsePacket = new DatagramPacket(data2, data2.length, address, port);
//发送响应信息
socket.send(responsePacket);
} catch (IOException e) {
e.printStackTrace();
}
}
}
未陌
你前面那个服务器端的代码都没有放到main方法里去。
UDPserver us = new UDPserver();
你用的这种方式根本就不能够调用上面的那些方法,因为这个是创建实例对象......而你想要的是运用那些方法。
DHChan
这说明服务器端的编码和客户端编码不一致,一致的话就不会乱码
liujie3300
你把UDPServer中的:DatagramSocket socket=new DatagramSocket(8800),改为DatagramSocket socket=null;然后在死循环中初始化socket=new DatagramSocket(8800);这是因为UDP是一种临时的协议,每次传输完数据close之后,都必须再次创建
陶路
可以把服务器端程序停止运行,在重新启动下服务器端和客户端试下。
吃炸鸡
1,首先大学的课本比较老,jdk可能版本不一样;
2,你说的"socket编程为什么不好用send/recieve方"是什么意思? 是"send/recieve方法"方法不好用吗?我已经通过使用了,建议你好好检查一下,应该可以解决的,细节注定成败;
3,慕课网的授课老师都是有实际经验的,所以建议直接copy使用,之后再扩展;
4,把视频案例debug一下,之后再去考虑各种疑问,尝试去解答;
最后送给在校的你,世界上有两种人最可怕,一种是能创造的人,一种是copy之后扩展的人,对于我们大多数人来说都是后者,先学好编程,就是多codeing,然后去思考,然后去扩展,基础必然重要,思想其实更重要。
Dddyx
其实你在使用的是eclipse的话,它会自动提示异常的,你可以直接把异常向外抛,再到最后统一处理