服务器-java 关于NIO实现UDP数据传输问题 ,急谢谢,C币不足请不要介意

问题描述

java 关于NIO实现UDP数据传输问题 ,急谢谢,C币不足请不要介意
各位大侠好,小弟想问一下问题,搞了一两天没有搞明白的。因为要实现一个UDP传输服务端,于是在网上找了很多资料然后就写了一个。但是写好之后发现有两个很严重的问题,希望各位大哥给点意见或者思路去解决。
问题一:启动服务端,同时也启动客户端,客户端传输数据服务器正常接收,但是断开客户端后,再启动客户端,服务器就收不到任何客户端发送的消息,好像是服务器关闭了UDP一样,但是重启服务器后(重新打开UDP)客户端既可以发送信息过来。
问题二:多个客户端。第一个客户端连接上后,第二个客户端怎么也链接不上了。即使关闭了第一个客户端也一样。
如下是代码:
package com.gateway.socket;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;
import java.util.Set;

import org.apache.log4j.Logger;

public class UDPEchoServerSelector extends Thread {

private static final Logger log = Logger.getLogger(ServerSocket.class);//private InetSocketAddress inetSocketAddress;// socket处理类private UDPSocketHandler handler = new UDPSocketHandler();// 注册的接受服务private SocketReceiver receiver = null;/** * 初始化socket *  * @param receiver * @param hostname * @param port * @throws IOException * @throws UnknownHostException */public UDPEchoServerSelector(SocketReceiver receiver String hostname        int port) {    if (hostname.isEmpty()) {        inetSocketAddress = new InetSocketAddress(port);    } else {        inetSocketAddress = new InetSocketAddress(hostname port);    }    this.receiver = receiver;}@Overridepublic void run() {    try {        Selector selector = Selector.open(); // 创建选择器,可以处理多路通道。        DatagramChannel serverSocketChannel = DatagramChannel.open(); // 打开通道        serverSocketChannel.configureBlocking(false); // 非阻塞        serverSocketChannel.socket().bind(inetSocketAddress);        /*         * 将通道管理器和该通道绑定,并为该通道注册SelectionKey.OP_READ事件注册该事件后,         * 当该事件到达时,selector.select()会返回,如果该事件没到达selector.select()会一直阻塞。         */        serverSocketChannel.register(selector SelectionKey.OP_READ                new ClientData());        log.info(""Server: socket server started."");        /*         * 采用轮询的方式监听selector上是否有需要处理的事件,如果有,则进行处理         */        while (true) { // 轮询            // 当注册的事件到达时,方法返回;否则该方法会一直阻塞            int nKeys = selector.select();            if (nKeys == 0) {                continue;            }            // 得到选择键列表            Set Keys = selector.selectedKeys();            Iterator it = Keys.iterator();            while (it.hasNext()) {                SelectionKey key = null;                key = (SelectionKey) it.next(); // 键为位掩码                it.remove();                // 客户端请求连接事件                if (key.isValid() && key.isWritable()) {                    log.info(""Server: SelectionKey is acceptable."");                    handler.handleWrite(key);                }                if (key.isReadable()) {// 获得了可读的事件                    log.info(""Server: SelectionKey is readable."");                    handler.receiveMsg(key receiver);                }            }            Keys.clear();        }    } catch (IOException e) {        e.printStackTrace();    }}public static class ClientData {    public SocketAddress clientAddress;    public ByteBuffer buffer = ByteBuffer.allocate(255);}

}

package com.gateway.socket;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import org.apache.log4j.Logger;
import com.gateway.common.DeviceDataTools;
import com.gateway.common.data.HexUtils;
import com.gateway.socket.UDPEchoServerSelector.ClientData;

/**

  • 处理socket类
  • @author Andy
  • */
    public class UDPSocketHandler {

    private static Logger log = Logger.getLogger(UDPSocketHandler.class);

    /**

    • 链接请求
    • @throws IOException
      */
      public void handleWrite(SelectionKey key) {
      try {
      DatagramChannel channel = (DatagramChannel) key.channel();
      ClientData clntDat = (ClientData) key.attachment();
      clntDat.buffer.flip(); // 从起始位置开始发送
      int bytesSent;

      bytesSent = channel.send(clntDat.buffer clntDat.clientAddress);if (bytesSent != 0) {    key.interestOps(SelectionKey.OP_READ); // 关注客户端发送数据}

      } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      }

    }

    /**

    • 读请求
    • @throws IOException
      */
      public void receiveMsg(SelectionKey key SocketReceiver receiver) {

      ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
      byteBuffer.clear();
      DatagramChannel socketChannel = (DatagramChannel) key.channel();

      //非阻塞
      try {
      socketChannel.configureBlocking(false);
      } catch (IOException e1) {
      // TODO Auto-generated catch block
      e1.printStackTrace();
      }

      System.out.println(""channel code:"" + socketChannel.hashCode());

      try {
      while (true) {

          InetSocketAddress client = (InetSocketAddress) socketChannel            .receive(byteBuffer);    byteBuffer.flip();    // byteBuffer中传过来的是10进制的bytep[]    byte[] dst = new byte[byteBuffer.limit()];    byteBuffer.get(dst);    // 将10进制的byte[]转化成16进制字符串    String data = HexUtils.converBytesToHex(dst);    System.out.println(data);    log.info(""Server: data1 = "" + data);    byteBuffer.clear();    receiver.udpreceive(socketChannel data client);    break;}

      } catch (java.io.IOException e) {
      //e.printStackTrace();
      //this.closeChannel(key socketChannel);
      } catch (Exception e) {
      //e.printStackTrace();
      //this.closeChannel(key socketChannel);
      }

    }

    /**

    • @param socketChannel*/private void closeChannel(SelectionKey key DatagramChannel socketChannel) {try { while (socketChannel.isOpen()) { key.cancel(); socketChannel.close(); }} catch (IOException e1) { e1.printStackTrace();}}

    /**

    • 根据socketKey从内存中获取channel,通过channel向client端发送消息
    • @param socketKey
    • 内存在channel对应的key
    • @param data
    • 发送的数据
    • @return
    • @throws IOException
      */
      public static boolean send(String socketKey String data)
      throws IOException {

      DatagramChannel socketChannel = SocketChannelMapper
      .getUDPChannel(socketKey);

      if (socketChannel == null || !socketChannel.isOpen()) {
      return false;
      }
      InetSocketAddress client = SocketChannelMapper
      .getUDPInetSocketAddress(socketKey + ""address"");
      boolean f = socketChannel.isConnected();
      ByteBuffer byteBuffer = ByteBuffer.wrap(DeviceDataTools.hex2Byte(data));
      if (f) {
      socketChannel.write(byteBuffer);
      } else {
      socketChannel.connect(new InetSocketAddress(client.getAddress()
      client.getPort()));
      socketChannel.send(byteBuffer client);
      }
      return true;
      }

    /**

    • 根据socketKey从内存中获取channel,通过channel向client端发送消息
    • @param socketKey
    • 内存在channel对应的key
    • @param data
    • 发送的数据
    • @return
    • @throws IOException
      */
      public static boolean send(DatagramChannel socketChannel String data
      InetSocketAddress client) throws IOException {

      if (socketChannel == null) {
      return false;
      }
      System.out.println(""#########################ADDRESS""
      + client.getAddress());
      System.out.println(""#########################PORT"" + client.getPort());

      boolean f = socketChannel.isConnected();

      ByteBuffer byteBuffer = ByteBuffer.wrap(DeviceDataTools.hexStr2ByteArray(data));

      if (f) {
      socketChannel.write(byteBuffer);
      } else {
      socketChannel.connect(new InetSocketAddress(client.getAddress()
      client.getPort()));
      socketChannel.send(byteBuffer client);
      }

      return true;
      }
      }

解决方案

建议楼主建一个服务器,多个客户端测试一下

解决方案二:
@模范青蛙,请问一下代码有没有问题?我目前就是将本机作为服务器来测试的

时间: 2024-08-03 17:20:33

服务器-java 关于NIO实现UDP数据传输问题 ,急谢谢,C币不足请不要介意的相关文章

服务器-java http/https转socket/udp

问题描述 java http/https转socket/udp 客户端使用的是http/https发送数据到到服务器,服务器使用的是tcp/udp, http/https和socket/udp之间怎么转换? 解决方案 http://jingyan.baidu.com/article/08b6a591e07ecc14a80922f1.html

java的nio之:java的nio系列教程之概述

一:java的nio的核心组件?Java NIO 由以下几个核心部分组成: ==>Channels ==>Buffers ==>Selectors 虽然Java NIO 中除此之外还有很多类和组件,但在我看来,Channel,Buffer 和 Selector 构成了核心的API.其它组件,如Pipe和FileLock,只不过是与三个核心组件共同使用的工具类.因此,在概述中我将集中在这三个组件上.其它组 件会在单独的章节中讲到. Channel 和 Buffer 基本上,所有的 IO 在

java的nio之:java的nio系列教程之channel的概念

一:java的nio的channel Java NIO的通道类似流,但又有些不同: ==>既可以从通道中读取数据,又可以写数据到通道.但流的读写通常是单向的. ==>通道可以异步地读写. ==>通道中的数据总是要先读到一个Buffer,或者总是要从一个Buffer中写入. 正如上面所说,从通道读取数据到缓冲区,从缓冲区写入数据到通道.如下图所示: 二:java的nio的channel的实现 这些是Java NIO中最重要的通道的实现: ==>FileChannel  : ==>

java的nio之:java的nio系列教程之java的io和nio的区别

当学习了Java NIO和IO的API后,一个问题马上涌入脑海: 我应该何时使用IO,何时使用NIO呢?在本文中,我会尽量清晰地解析Java NIO和IO的差异.它们的使用场景,以及它们如何影响您的代码设计. Java NIO和IO的主要区别 下表总结了Java NIO和IO之间的主要差别,我会更详细地描述表中每部分的差异. IO                NIO 面向流            面向缓冲 阻塞IO           非阻塞IO 无 选择器   面向流与面向缓冲 Java N

哎哎哎!急-请求大神帮忙用JAVA写一个基于UDP的语音聊天系统

问题描述 请求大神帮忙用JAVA写一个基于UDP的语音聊天系统 有报酬!!?谢谢!!急急 解决方案 有报酬,两个馒头.呵呵...... UDP 实际简单,但语音部分还是有一些工作量的.

anroid javaweb-anroid客户端如何与服务器进行交互,并实现数据传输?

问题描述 anroid客户端如何与服务器进行交互,并实现数据传输? 最近实验室做一个城市智能停车诱导的项目,其中需要做一个APP主要,分为客户端和服务器端.但是不太清楚移动端如何与服务器端进行数据交互,想用mysql数据库和tomcat服务器,利用json进行数据之间传输.但是感觉无从下手,忘大神指点,最好有项目源码,分享学习一下,比如实现简单的用户注册账号并登陆. 解决方案 APP端编写用户输入界面,获取到用户的账号密码,用json发送出去,至于怎么发送,有好几种,但是有现成的框架,比如vol

开年发力!华为FusionServer 2路服务器Java应用性能领先

随着云计算和移动互联网的迅速兴起,也许你已经习惯每天登录银行的网上电子交易系统,进行账务查询.理财交易,习惯每天浏览热门网站的酷炫多媒体内容来获取外界资讯,习惯每天登录热门在线网游与上百万人实时竞技较量,但你是否意识到这些快速安全便捷的服务背后其实都很可能是基于Java技术开发的大规模应用正高效运行在服务器上的结果呢? Java应用程序在编译之后可以直接运行在不同的操作系统平台,具有卓越的通用性.高效性.平台移植性和安全性,当前Java技术已经广泛应用于企业级大型数据中心.高性能计算.银行电子交

java的nio之:java的nio系列教程之buffer的概念

一:java的nio的buffer==>Java NIO中的Buffer用于和NIO通道Channel进行交互.==>数据是从通道channel读入缓冲区buffer,从缓冲区buffer写入到通道中channel的.==>缓冲区buffer本质上是一块可以写入数据,然后可以从中读取数据的内存.这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存. 二:buffer的基本用法 ==>使用Buffer读写数据一般遵循以下四个步骤: 写入数据到Buffer

请问:java代码如何判断服务是否启动?谢谢!!

问题描述 请问:java代码如何判断服务是否启动?谢谢!! 急求: java代码如何判断服务是否启动?谢谢!! 解决方案 http://www.360doc.com/content/12/0711/09/2905268_223518890.shtml 解决方案二: 一般服务启动都是启动在某IP的某个端口上,通过Socket去连下你们服务启动的IP和端口.看是否能连的通.如果连的通,表示服务已启动,但请注意,服务启动不代表服务一定正常可用. 附上代码. /** * * 测试连接服务器 * * @p