我想學習Java。我想實現一個簡單的網絡連接4遊戲以及聊天功能。Java ServerSocketChannel SocketChannel(回調)
我想我的網絡邏輯是非阻塞的,所以經過多番研究後,我發現SocketChannel就是我在重新調整我的需求之後。
還沒有意義的是SocketChannel中缺少CallBack函數..就像在C#中發現的一樣。
我現在的查詢是:如何將收到的數據傳遞給聊天或遊戲窗體(JFrame)?
一些指導是最受歡迎的。
我想學習Java。我想實現一個簡單的網絡連接4遊戲以及聊天功能。Java ServerSocketChannel SocketChannel(回調)
我想我的網絡邏輯是非阻塞的,所以經過多番研究後,我發現SocketChannel就是我在重新調整我的需求之後。
還沒有意義的是SocketChannel中缺少CallBack函數..就像在C#中發現的一樣。
我現在的查詢是:如何將收到的數據傳遞給聊天或遊戲窗體(JFrame)?
一些指導是最受歡迎的。
您需要使用選擇器。首先創建一個選擇接收的事件:
Selector selector = Selector.open()
然後,你需要註冊與選擇的的ServerSocketChannel:
SelectionKey acceptKey = server.register(selector, SelectionKey.OP_ACCEPT);
然後,你需要使用選擇,因爲他們進來處理事件(你可以認爲這是該過程的「回調」的一部分:
while(true){
//how many channel keys are available
int available = selector.select();
//select is blocking, but should only return if available is >0, this is more of a sanity check
if(available == 0) continue;
Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while(keys.hasNext()){
SelectionKey key = keys.next();
keys.remove();
//someone is trying to connect to the server socket
if(key.isAcceptable()) doAccept(key);
//someone is sending us data
else if(key.isReadable()) doRead(key);
//we are trying to (and can) send data
else if(key.isWritable()) doWrite(key);
}
肉將在doAccept(),doRead(),和doWrite()對於接受鍵選擇鍵將包含INF。 ormation來創建新的Socket。
doAccept(SelectionKey key){
//create the new socket
SocketChannel socket = ((ServerSocketChannel)key.channel()).accept();
//make it non-blocking as well
socket.configureBlocking(false);
...
//here you would likely have some code to init your game objects/communication protocol, etc. and generate an identifier object (used below).
//and be able to find the socket created above
...
//Since it is non blocking it needs a selector as well, and we register for both read and write events
SelectionKey socketKey = socket.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE);
// so we can identify the events as they come in
socketKey.attach(someSocketIndentifier);
}
最後一行添加了一些對象的鍵,以便從選擇接收的事件可以歸結爲一個連接(例如,它可能是在你的遊戲玩家)。所以現在你可以接受新的連接,你只需要讀寫。
doRead(SelectionKey key){
//here we retrieve the key we attached earlier, so we now what to do/wheer the data is coming from
MyIdentifierType myIdentifier = (MyIdentifierType)key.attachment();
//This is then used to get back to the SocketChannel and Read the Data
myIdentifier.readTheData();
}
同樣寫
doWrite(SelectionKey key){
//here we retrieve the key we attached earlier, so we now what to do/wheer the data is coming from
MyIdentifierType myIdentifier = (MyIdentifierType)key.attachment();
//This is then used to get back to the SocketChannel and Read the Data
myIdentifier.getSocketHandler().writePendingData();
}
閱讀是相當簡單的,你只需要創建一個字節緩衝區,然後調用SocketChannels讀取(字節緩衝區)(及其變種或一個),準備好這些數據上該頻道直到它空了。
寫作是有點棘手,你通常會希望緩衝要寫入的數據,直到你收到寫事件:
class MyNetworkClass{
ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
SocketChannel commchannel; //from the server accept processing
...
public void write(byte[] data){
//here the class writeBuffer object is filled with the data
//but it isn't actually sent over the socket
...
}
public void writePendingData(){
//here actually write the data to the socket
commchannel.write(writeBuffer);
}
}
請注意,您將需要適當的代碼來管理類的緩衝事件變滿了,或者如果緩衝區中的數據沒有全部寫入套接字,則可以在寫掛起方法中適當修改它,以及在此過程中可能拋出的各種異常。希望這有助於你開始。
這一直非常有用,我現在更瞭解這個過程。 – iTEgg 2010-04-21 19:27:01
我建議你使用多線程而不是非阻塞I/O。 – 2010-04-21 18:46:34