我有一个同步客户端,如何制作这个异步客户端?客户端连接正确,然后写入通道,然后等待(没有键准备好,因为没有任何东西可以从通道读取),现在我希望它再次开始写入通道,如何实现这一点?感谢
public class Client {
static class SocketTest implements Runnable {
private Selector selector;
private int sessionID = 0;
int port;
String address;
private List<Message> dummyTypeOneResults = new LinkedList<Message>();
private List<Message> dummyTypeTwoResults = new LinkedList<Message>();
public SocketTest(String address, int port){
this.port = port;
this.address = address;
}
@Override
public void run() {
SocketChannel channel;
try {
selector = Selector.open();
channel = SocketChannel.open();
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_CONNECT);
channel.connect(new InetSocketAddress(this.address,this.port));
while (!Thread.interrupted()){
selector.selectNow();
Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while (keys.hasNext()){
SelectionKey key = keys.next();
keys.remove();
if (!key.isValid()) continue;
if (key.isConnectable()){
connect(key);
}
if (key.isWritable()){
if(sessionID > 200000){
//force disconnect
System.out.println("sessionID reached limit forcing disconnet");
key.cancel();
//call calculate
calculate();
close();
return;
} else {
write(key);
}
}
if (key.isReadable()){
read(key);
}
}
}
} catch (IOException e1) {
e1.printStackTrace();
} finally {
close();
}
}
private void calculate() throws IOException{
//open file
File file = new File("results_nio.txt");
// if file doesnt exists, then create it
FileWriter fw = null;
fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
long totalDifferenceSum = 0;
long messageCount = 0;
for (Message message : dummyTypeOneResults) {
long diff = message.getProcessed() - message.getDispatched();
String out = "message with ID: "+message.getSessionID()+" Trip time in seconds %f %n ";
System.out.format(out,diff/1000000000.0);
bw.write(String.format(out,diff/1000000000.0));
totalDifferenceSum +=diff;
messageCount++;
}
for (Message message : dummyTypeTwoResults) {
long diff = message.getProcessed() - message.getDispatched();
String out = "message with ID: "+message.getSessionID()+" Trip time in seconds %f %n ";
System.out.format(out,diff/1000000000.0);
bw.write(String.format(out,diff/1000000000.0));
totalDifferenceSum +=diff;
messageCount++;
}
String totalString = "Total round trip time in seconds %f %n ";
System.out.format(totalString,totalDifferenceSum/1000000000.0);
bw.write(String.format(totalString,totalDifferenceSum/1000000000.0));
double average = messageCount > 0 ? (double)totalDifferenceSum/messageCount : 0;
String averageString = "Average trip time in seconds %f %n ";
System.out.format(averageString,average/1000000000.0);
bw.write(String.format(averageString,average/1000000000.0));
bw.close();
}
private void close(){
try {
selector.close();
} catch (IOException e) {
System.err.println(e);
}
}
private void read(SelectionKey key) throws IOException {
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer readBuffer = ByteBuffer.allocate(1024);
int length;
try {
length = channel.read(readBuffer);
System.out.println("Bytes read from server: "+length);
if(length != -1){
byte[] bytes;
readBuffer.flip();
bytes = new byte[readBuffer.remaining()];
readBuffer.get(bytes, 0, bytes.length);
//create Message
ByteBuffer prepareBuffer = ByteBuffer.wrap(bytes);
int type = prepareBuffer.getInt();
int sessionID = prepareBuffer.getInt();
long dispatched = prepareBuffer.getLong();
Message message = new Message(sessionID, type, dispatched, bytes);
message.setProcessed(System.nanoTime());
if(type == Message.DUMMY_ONE){
dummyTypeOneResults.add(message);
} else if (type == Message.DUMMY_TWO) {
dummyTypeTwoResults.add(message);
}
}
} catch (IOException e) {
System.out.println("Reading problem, closing connection");
key.cancel();
channel.close();
return;
}
if (length == -1) {
System.out.println("Nothing was read from server");
//channel.close();
key.cancel();
System.out.println("Send againg new message ");
key.interestOps(SelectionKey.OP_CONNECT);
return;
}
readBuffer.flip();
byte[] buff = new byte[1024];
readBuffer.get(buff, 0, length);
key.interestOps(SelectionKey.OP_WRITE);
readBuffer.clear();
}
private void write(SelectionKey key) throws IOException {
//Message format |typeID|sessionID|startTime
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer message = ByteBuffer.allocate(16);
if(sessionID % 2 == 0){
message.putInt(Message.DUMMY_ONE);
} else {
message.putInt(Message.DUMMY_TWO);
}
message.putInt(sessionID);
message.putLong(System.nanoTime());
sessionID++;
message.flip();
int bytesWritten = channel.write(message);
System.out.println("client write(): bytesWritten :"+bytesWritten);
// lets get ready to read.
key.interestOps(SelectionKey.OP_READ);
}
private void connect(SelectionKey key) throws IOException {
SocketChannel channel = (SocketChannel) key.channel();
if (channel.isConnectionPending()){
boolean finished = channel.finishConnect();
if (!finished) {
key.cancel();
}
}
channel.configureBlocking(false);
channel.register(selector,SelectionKey.OP_WRITE); // \p was
// channel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
}
}
public static void main(String[] args) {
int DEFAULT_PORT = 9090;
String IP = "127.0.0.1";
if(args.length > 1){
if(args[0]!=null){
IP=args[0];
}
if(args[1]!=null){
DEFAULT_PORT=Integer.valueOf(args[1]);
}
}
new Thread(new SocketTest(IP,DEFAULT_PORT)).start();
}
//和Message class
public class Message implements Serializable {
public static final int DUMMY_ONE = 1;
public static final int DUMMY_TWO = 2;
private static final long serialVersionUID = -555511105603152223L;
// could be message header
protected int sessionID;
protected int type;
protected long created = System.currentTimeMillis();
protected long dispatched;
protected long processed;
protected Object payload;
public Message(int sessionID, int type, long dispatched) {
super();
this.sessionID = sessionID;
this.type = type;
this.dispatched = dispatched;
}
public Message(int sessionID, int type, long dispatched, Object payload) {
super();
this.sessionID = sessionID;
this.type = type;
this.dispatched = dispatched;
this.payload = payload;
}
public int getSessionID() {
return sessionID;
}
public void setSessionID(int sessionID) {
this.sessionID = sessionID;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public long getCreated() {
return created;
}
public void setCreated(long created) {
this.created = created;
}
public long getDispatched() {
return dispatched;
}
public void setDispatched(long dispatched) {
this.dispatched = dispatched;
}
public long getProcessed() {
return processed;
}
public void setProcessed(long processed) {
this.processed = processed;
}
public Object getPayload() {
return payload;
}
public void setPayload(Object payload) {
this.payload = payload;
}
@Override
public String toString() {
return "Message [sessionID=" + sessionID + ", type=" + type
+ ", created=" + created + ", dispatched=" + dispatched + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (created ^ (created >>> 32));
result = prime * result + (int) (dispatched ^ (dispatched >>> 32));
result = prime * result + ((payload == null) ? 0 : payload.hashCode());
result = prime * result + (int) (processed ^ (processed >>> 32));
result = prime * result + sessionID;
result = prime * result + type;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Message other = (Message) obj;
if (created != other.created)
return false;
if (dispatched != other.dispatched)
return false;
if (payload == null) {
if (other.payload != null)
return false;
} else if (!payload.equals(other.payload))
return false;
if (processed != other.processed)
return false;
if (sessionID != other.sessionID)
return false;
if (type != other.type)
return false;
return true;
}
}
答案 0 :(得分:0)
你在'异步'和'非阻塞'之间感到困惑。
您正在非阻止模式下操作,但是您在select().
阻止这是正常的。
如果您想要异步I / O,则需要使用AsynchronousSocketChannel
。这是一个完全不同的编程范例。