我在下面使用Java Nio进行客户端服务器通信是客户端和服务器的代码。
服务器:
public class BufferChannelExample {
private static String clientChannel = "clientChannel";
private static String serverChannel = "serverChannel";
private static String channelType = "channelType";
private static Selector selector = null;
static BufferChannelExample bufferChannelExample = null;
static int port1 = 1114;
//static String localhost1 = "192.168.1.35";
static String localhost1 = "192.168.1.88";
ByteBuffer buffer;
static String msgFromClient = "";
static MsgSaver msgSaver;
public static void main(String[] args) {
// readFileChannel();
//msgSaver = new MsgSaver();
bufferChannelExample = new BufferChannelExample();
serverSocketExample();
}
public static void writeToChannels() {
if(selector == null)
return;
if(!selector.isOpen())
return;
Set multipleKeys = selector.keys();
System.out.println("multipleKeys.size() : "+multipleKeys.size());
for (int i = 0; i < multipleKeys.size(); i++) {
System.out.println("multipleKeys: "+multipleKeys.toString());
}
MulticastSocket multicastSocket = null;
try {
multicastSocket = new MulticastSocket(port1);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Iterator<SelectionKey> mkIterator = multipleKeys.iterator();
while (mkIterator.hasNext()) {
SelectionKey sKey = mkIterator.next();
// System.out.println("mk rAddr : "+((SocketChannel)sKey.channel()).getRemoteAddress().toString());
// if(sKey == key){
// if((sKey.readyOps() & SelectionKey.OP_ACCEPT) != SelectionKey.OP_ACCEPT){
if(((Map<?, ?>) sKey.attachment()).get(channelType).equals(
clientChannel)){
System.out.println("isWritable() --- > "+sKey.isWritable());
System.out.println("RemoteSocketAddress : "+((SocketChannel)sKey.channel()).socket().getRemoteSocketAddress());
// write something to the new created client
CharBuffer buffer;
if(msgFromClient.equalsIgnoreCase(""))
{
buffer = CharBuffer.wrap("Hello client new!!! ---stop");
System.out.println("if--");
}
else {
Iterator iter = multipleKeys.iterator();
while (iter.hasNext()) {
System.out.println(iter.next());
}
buffer = CharBuffer.wrap(msgFromClient);
System.out.println("else--");
}
//System.out.println("msgFromClient----"+msgSaver.getMsg());
while (buffer.hasRemaining()) {
try {
((SocketChannel)sKey.channel()).write(Charset.defaultCharset()
.encode (buffer));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
buffer.clear();
}
// }
}
}
private static void serverSocketExample() {
ArrayList<String> remoteAddressArray = new ArrayList<String>();
ServerSocketChannel channel1;
try {
channel1 = ServerSocketChannel.open();
channel1.socket().bind(new InetSocketAddress(localhost1, port1));
channel1.configureBlocking(false);
// create a selector that will by used for multiplexing. The selector
// registers the socketserverchannel as
// well as all socketchannels that are created
selector = Selector.open();
// register the serversocketchannel with the selector. The OP_ACCEPT
// option marks
// a selection key as ready when the channel accepts a new connection.
// When the
// socket server accepts a connection this key is added to the list of
// selected keys of the selector.
// when asked for the selected keys, this key is returned and hence we
// know that a new connection has been accepted.
SelectionKey socketServerSelectionKey = channel1.register(selector,
SelectionKey.OP_ACCEPT);
// set property in the key that identifies the channel
// Map<String, String=""> properties = new HashMap<string, string="">();
Map<String, String> properties = new HashMap<String, String>();
properties.put(channelType, serverChannel);
socketServerSelectionKey.attach(properties);
// wait for the selected keys
for (;;) {
// System.out.println("waiting for keys");
// the select method is a blocking method which returns when atleast
// one of the registered
// channel is selected. In this example, when the socket accepts a
// new connection, this method
// will return. Once a socketclient is added to the list of
// registered channels, then this method
// would also return when one of the clients has data to be read or
// written. It is also possible to perform a nonblocking select
// using the selectNow() function.
// We can also specify the maximum time for which a select function
// can be blocked using the select(long timeout) function.
if (selector.select() == 0)
continue;
// the select method returns with a list of selected keys
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectedKeys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
// System.out.println("SelectionKey "+key.toString());
// the selection key could either by the socketserver informing
// that a new connection has been made, or
// a socket client that is ready for read/write
// we use the properties object attached to the channel to find
// out the type of channel.
if (((Map<?, ?>) key.attachment()).get(channelType).equals(
serverChannel)) {
// a new connection has been obtained. This channel is
// therefore a socket server.
ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key
.channel();
// accept the new connection on the server socket. Since the
// server socket channel is marked as non blocking
// this channel will return null if no client is connected.
SocketChannel clientSocketChannel = serverSocketChannel
.accept();
if (clientSocketChannel != null) {
// set the client connection to be non blocking
clientSocketChannel.configureBlocking(false);
SelectionKey clientKey = clientSocketChannel.register(
selector, SelectionKey.OP_READ| SelectionKey.OP_WRITE);
Map<String, String> clientproperties = new HashMap<String, String>();
clientproperties.put(channelType, clientChannel);
clientKey.attach(clientproperties);
// write something to the new created client
CharBuffer buffer = CharBuffer.wrap("Hello client from server");
while (buffer.hasRemaining()) {
// clientSocketChannel.write(Charset.defaultCharset()
// .encode(buffer));
clientSocketChannel.write(Charset.defaultCharset()
.encode(buffer));
}
buffer.clear();
}
} else {
// data is available for read
// buffer for reading
ByteBuffer buffer = ByteBuffer.allocate(100);
SocketChannel clientChannel = (SocketChannel) key.channel();
int bytesRead = 0;
if (key.isReadable()) {
// the channel is non blocking so keep it open till the
// count is >=0
if ((bytesRead = clientChannel.read(buffer)) > 0) {
buffer.flip();
// System.out.println("message from client ---> "+Charset.defaultCharset().decode(
// buffer));
msgFromClient = Charset.defaultCharset().decode(buffer).toString();
//msgSaver.setMsg(Charset.defaultCharset().decode(buffer).toString());
System.out.println("msgFromClient111----"+Charset.defaultCharset().decode(buffer).toString());
writeToChannels();
// if(th == null){
// th = new Thread(new NewRunnable());
// th.start();
// }
buffer.clear();
}
if (bytesRead < 0) {
// the key is automatically invalidated once the
// channel is closed
clientChannel.close();
}
}
}
// once a key is handled, it needs to be removed
iterator.remove();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
static Thread th = null;
}
}
客户端:
公共类ExampleClient2 {
public static void main(String[] args) throws IOException,
InterruptedException {
int port = 1114;
SocketChannel channel = SocketChannel.open();
// we open this channel in non blocking mode
channel.configureBlocking(false);
channel.connect(new InetSocketAddress("192.168.1.88", port));
if(!channel.isConnected())
{
while (!channel.finishConnect()) {
System.out.println("still connecting");
}
}
System.out.println("connected...");
while (true) {
// see if any message has been received
ByteBuffer bufferA = ByteBuffer.allocate(60);
int count = 0;
String message = "";
while ((count = channel.read(bufferA)) > 0) {
// flip the buffer to start reading
bufferA.flip();
message += Charset.defaultCharset().decode(bufferA);
}
if (message.length() > 0) {
System.out.println("message " + message);
if(message.contains("stop"))
{
System.out.println("Has stop messages");
// break;
}
else
{
// write some data into the channel
CharBuffer buffer = CharBuffer.wrap("Hello Server stop from client2 from 88");
while (buffer.hasRemaining()) {
channel.write(Charset.defaultCharset().encode(buffer));
}
}
message = "";
}
}
}
}
如果我从同一客户端请求服务器两次,服务器将视为新客户端并创建新连接。如何检测消息来自旧客户端,而不需要创建新连接。
感谢。
答案 0 :(得分:0)
您可以在应用程序中引入HTTP会话管理,然后根据会话ID跟踪每个客户端请求。然后,您可以让您的应用程序适应这种情况。
如果您的服务器使用Servlet技术,则添加Servlet过滤器以拦截所有传入请求会更加容易。