Я пытаюсь прочитать из DatagramChannel cchannel_dtg в буфер inBuffer.
Я использую вызов select () для перебора ключей и соответствующих им каналов UDP, для чтения и записи.У меня также есть подобный кусок кода для TCP, который работает отлично, принимает много клиентов и возвращает их сообщения.
Однако, для этого фрагмента кода UDP, он терпит неудачу в строке bytesRecv = cchannel_dtg.read(inBuffer);
из-за чтения () вызов (во время выполнения, когда я пытаюсь отправить сообщение со стороны клиента, он компилируется нормально).Исключение: java.nio.channels.NotYetConnectedException
.
Я попытался выполнить вызов receive () вместо read (), который возвращает адрес принимающего клиента, но затем он блокировал некоторые другие соединения и взаимодействие сервера с клиентом не было удовлетворительным.
Кто-нибудь знает причину или решение?
public class SelectServer {
public static int BUFFERSIZE = 32;
public static void main(String args[]) throws Exception
{
if (args.length != 1)
{
System.out.println("Usage: UDPServer <Listening Port>");
System.exit(1);
}
// Initialize buffers and coders for channel receive and send
String line = "";
//Encoder and decoders between bytes<->chars
Charset charset = Charset.forName( "us-ascii" ); //For converting 16-bit unicode characters to bytes.
CharsetDecoder decoder = charset.newDecoder(); // Transform a sequence of bytes into a sequence of 16-bit Unicode characters.
CharsetEncoder encoder = charset.newEncoder(); // Transform 16-bit Unicode characters into a bytes.
ByteBuffer inBuffer = null; //Buffer to send data
CharBuffer outBuffer = null; //Buffer to convert inbuffer's bytes to chars
int bytesSent, bytesRecv; // number of bytes sent or received - for error checking if msg was delivered to client
// Initialize the selector
Selector selector = Selector.open(); //Can examine one or more Java NIO Channel instances,
// and determine which channels are ready for e.g. reading or writing.
// This way a single thread can manage multiple channels,
// and thus multiple network connections.
/** TCP CHANNEL CREATION */
// Create a server channel and make it non-blocking
ServerSocketChannel tcp_channel = ServerSocketChannel.open(); //tcp_channel that can listen for incoming TCP connections,
// just like a ServerSocket in standard Java Networking.
tcp_channel.configureBlocking(false); //Adjusts this channel's blocking mode.
// Get the port number and bind the socket
InetSocketAddress isa1 = new InetSocketAddress(Integer.parseInt(args[0])); //Socket Address with specific port and wildcard IP address.
tcp_channel.socket().bind(isa1); //Assign port and IP wildcard address to socket.
// Register that the server selector is interested in connection requests
tcp_channel.register(selector, SelectionKey.OP_ACCEPT);
/** UDP CHANNEL CREATION */
//UDP Server
DatagramChannel udp_channel = DatagramChannel.open();
udp_channel.configureBlocking(false);
InetSocketAddress isa2 = new InetSocketAddress(Integer.parseInt(args[0]));
udp_channel.socket().bind(isa2);
udp_channel.register(selector, SelectionKey.OP_READ);
// Wait for something happen among all registered sockets
try {
boolean terminated = false;
while (!terminated)
{
if (selector.select(500) < 0) //500miliseconds
{
System.out.println("select() failed");
System.exit(1);
}
// Get set of ready sockets
Set readyKeys = selector.selectedKeys(); //selector's selected keys set
Iterator readyItor = readyKeys.iterator();
// Walk through the ready set
while (readyItor.hasNext())
{
// Get 1 key from set {key,key,key..}
SelectionKey key = (SelectionKey)readyItor.next();
// Remove current key entry from iteration because we saved that key in a variable "key"
readyItor.remove();
// Accept new connections, if any
if (key.isAcceptable()) //if socket is accepting connections & has some to accept
{
SocketChannel cchannel = ((ServerSocketChannel)key.channel()).accept();
cchannel.configureBlocking(false);
System.out.println("Accept conncection from " + cchannel.socket().toString());
// Register the new connection for read operation
cchannel.register(selector, SelectionKey.OP_READ);
}
else
{
SocketChannel cchannel;
DatagramChannel cchannel_dtg;
try{
cchannel = (SocketChannel)key.channel();
System.out.println("Connection coming from TCP server");
if (key.isReadable())
{
Socket socket = cchannel.socket();
// Open input and output streams (Receive bytes but send chars)
inBuffer = ByteBuffer.allocateDirect(BUFFERSIZE); //Size of outBuffer to accomodate BUFFERSIZE bytes to receive.
outBuffer = CharBuffer.allocate(BUFFERSIZE); //Size the inBuffer to accomodate BUFFERSIZE bytes to send
// Read from socket
bytesRecv = cchannel.read(inBuffer);
if (bytesRecv <= 0)
{
System.out.println("read() error, or connection closed");
key.cancel(); // deregister the socket
continue;
}
inBuffer.flip(); // make buffer available
decoder.decode(inBuffer, outBuffer, false);
outBuffer.flip();
line = outBuffer.toString();
System.out.println("Client: " + line);
// Echo the message back
inBuffer.flip();
bytesSent = cchannel.write(inBuffer); //write bytes to socket
if (bytesSent != bytesRecv)
{
System.out.println("write() error, or connection closed");
key.cancel(); // deregister the socket
continue;
}
if (line.equals("terminate\n"))
terminated = true;
}
}catch (ClassCastException e){}
try{
cchannel_dtg = (DatagramChannel)key.channel();
System.out.println("Connection coming from UDP server");
if (key.isReadable())
{
// Declare a UDP server socket
DatagramSocket echoServer = cchannel_dtg.socket();
if (args.length != 1)
{
System.out.println("Usage: UDPServer <Listening Port>");
System.exit(1);
}
// Try to open a server socket on the given port
// Note that we can't choose a port less than 1023 if we are not
// privileged users (root)
try {
// As long as we receive data, echo that data back to the client.
inBuffer = ByteBuffer.allocateDirect(BUFFERSIZE);
outBuffer = CharBuffer.allocate(BUFFERSIZE); //Size the inBuffer to accomodate BUFFERSIZE bytes to send
// Receive data into inBuffer from the socket
bytesRecv = cchannel_dtg.read(inBuffer);
if (bytesRecv <= 0)
{
System.out.println("read() error, or connection closed");
key.cancel(); // deregister the socket
continue;
}
inBuffer.flip(); // make buffer available
decoder.decode(inBuffer, outBuffer, false);
outBuffer.flip();
line = outBuffer.toString();
if(!line.equals("")){
System.out.println("Client: " + line);
}
// Echo the message back
inBuffer.flip();
bytesSent = cchannel_dtg.write(inBuffer); //write bytes to socket
if (bytesSent != bytesRecv)
{
System.out.println("write() error, or connection closed");
key.cancel(); // deregister the socket
continue;
}
if (line.equals("terminate\n")){terminated = true;}
}catch(IOException e) {
System.out.println(e);
}
}
} catch(ClassCastException e){}
}
} // end of while (readyItor.hasNext())
} // end of while (!terminated)
}catch(IOException e){System.out.println(e);}
// close all connections
Set keys = selector.keys();
Iterator itr = keys.iterator();
while (itr.hasNext())
{
SelectionKey key = (SelectionKey)itr.next();
//itr.remove();
if (key.isAcceptable()){
try{((ServerSocketChannel)key.channel()).socket().close();}catch(ClassCastException e){}
try{((DatagramChannel)key.channel()).socket().close();}catch(ClassCastException e){}
}
else if (key.isValid()){
try{((SocketChannel)key.channel()).socket().close();}catch(ClassCastException e){}
try{((DatagramChannel)key.channel()).socket().close();}catch(ClassCastException e){}
}
}
}
} ```