سؤال

أحاول أن أتعلم جافا. أرغب في تنفيذ لعبة Connect 4 بسيطة بالإضافة إلى ميزة الدردشة.

أريد أن يكون منطق الشبكة الخاص بي غير حظر ، وبعد الكثير من الدراسة ، وجدت أن Socketchannel هو ما أنا عليه بعد إعادة تجهيز احتياجاتي.

ما لم يكن منطقيًا هو عدم وجود وظائف رد الاتصال في Socketchannels .. مثل اكتشاف واحد في C#.

استعلامي لهذا الوقت هو: كيف يمكنني تسليم البيانات المستلمة إلى نموذج الدردشة أو اللعبة (JFRAME)؟

بعض التوجيهات موضع ترحيب كبير.

هل كانت مفيدة؟

المحلول

تحتاج إلى استخدام محدد. قم أولاً بإنشاء محدد لتلقي الأحداث:

Selector selector = Selector.open()

ثم تحتاج إلى تسجيل خوادم CosterSocketchannel مع المحدد:

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 (). بالنسبة لمفتاح قبول ، سيحتوي مفتاح التحديد على المعلومات لإنشاء المقبس الجديد.

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();
}

القراءة مستقيمة إلى حد ما إلى حد ما ، يمكنك فقط إنشاء Bytebuffer ثم استدعاء القنوات القراءة (Bytebuffer) (أو أحد المتغيرات الخاصة به) لإعداد البيانات على القناة حتى فارغة.

الكتابة أكثر صعوبة بعض الشيء حيث أنك تريد عادة تخزين البيانات المراد كتابة حتى تتلقى حدث الكتابة:

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);
  }
}

لاحظ أنك ستحتاج إلى رمز مناسب لإدارة المخزن المؤقت في الفصل في حال يصبح ممتلئًا ، أو لتعديله بشكل مناسب في طريقة الكتابة المعلقة إن لم يكن كل البيانات في المخزن المؤقت مكتوبة على المقبس ، وكذلك الاستثناءات المختلفة التي يمكن إلقاؤها أثناء العملية. أتمنى أن يساعدك هذا في البدء.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top