gpt4 book ai didi

java - Android NIO 服务器选择器在没有消息发送时读取

转载 作者:行者123 更新时间:2023-12-01 04:32:18 25 4
gpt4 key购买 nike

我正在尝试使用 NIO 服务器来读取/写入 TCP 连接的客户端。我已成功建立连接,并且我的初始消息已发送到服务器并得到正确处理。它说服务器正在发回消息,但我没有收到客户端的任何输入。此外,在服务器发回消息后,应用程序崩溃,表示它正在尝试读取空指针(第 127 行服务器代码)。

需要注意的是,我对这个概念很陌生,而且我并不真正了解选择器。我看过教程,但矛盾的消息让我对这个问题更加困惑。如果有人有关于这个主题的任何好的教程,我将不胜感激。

这是我的代码。

客户主 Activity 屏幕

package com.example.client;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.example.client.ServerService.Connect;



public class MainActivity extends Activity {

Button button;
TextView textView;
EditText editText;
EditText editTextps;
static Handler handler;
Connect connect=null;
Object myLock=new Object();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button=(Button) findViewById(R.id.button1);
textView=(TextView) findViewById(R.id.textView1);
editText=(EditText) findViewById(R.id.editText1);
editTextps=(EditText) findViewById(R.id.editText2);
handler=new Handler(){
@Override
public void handleMessage(Message msg) { //Handle code for receiving messages
super.handleMessage(msg);//when a message is received it's input is processed here
Bundle bundle=msg.getData();
if(bundle.getInt("int") == 2){
if(bundle.getInt("valid") == 1){
Intent i = new Intent();
i.setClassName("com.example.client",
"com.example.client.ReadyScreen");
startActivity(i);
}else{
alertMessage();
editText.setText("");
editTextps.setText("");
}
}
}

};

startService(new Intent(getBaseContext(), ServerService.class));


button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
String str=editText.getText().toString();
String strps=editTextps.getText().toString();
Message msg=Message.obtain();
Bundle bundle=new Bundle();
bundle.putString("name", str);
bundle.putString("password", strps);
msg.setData(bundle);
ServerService.threadHandler.sendMessage(msg);
}
});
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

public void alertMessage() {

final android.app.AlertDialog.Builder show = new AlertDialog.Builder(this).setTitle("Error").setMessage("Wrong username/password").setNeutralButton("close", null);
show.show();
}
}

我运行连接和 IO 的服务器服务

package com.example.client;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;

public class ServerService extends Service {

Handler handler;
static MyHandle threadHandler;
Connect connect=null;
Object myLock=new Object();
static SocketChannel socketChannel=null;
public ByteBuffer sendBuffer=ByteBuffer.allocate(1024);
static ByteBuffer receiveBuffer=ByteBuffer.allocate(1024);
static Selector selector;
private static final String TAG = ServerService.class.getSimpleName();

@Override
public IBinder onBind(Intent intent) {
return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId){
Log.d(TAG, "Started running the service");
System.out.println(TAG + "Started running the service");

(new Thread(new ReceivingThread())).start();
(new Thread(new SendingThread())).start();

return START_STICKY;
}


@Override
public void onDestroy(){
super.onDestroy();
Toast.makeText(this, "Service Stopped", Toast.LENGTH_LONG).show();
}

class Connect {
SocketChannel socketChannel=null;
public ByteBuffer sendBuffer=ByteBuffer.allocate(1024);
ByteBuffer receiveBuffer=ByteBuffer.allocate(1024);
Selector selector;
public Connect() {

try {
socketChannel=SocketChannel.open();
SocketAddress remoteAddress=new InetSocketAddress("192.168.2.17", 20001);
socketChannel.connect(remoteAddress);
socketChannel.configureBlocking(false);
selector=Selector.open();
socketChannel.register(selector, SelectionKey.OP_READ);
} catch (Exception e) {

e.printStackTrace();
}
}
}

public class ReceivingThread implements Runnable{

@Override
public void run() {
Log.d(TAG, "Started running the receive thread");
connect=new Connect();
try {
while(true){
if(connect.selector.select()==0)
continue;
Play receivedMessage = new Play();
receivedMessage.play();
}
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
}
}

}

public class SendingThread implements Runnable{

@Override
public void run() {
Log.d(TAG, "Started running the send thread");
Looper.prepare();
threadHandler=new MyHandle(Looper.myLooper());
Looper.loop();
}

}

class MyHandle extends Handler{
public MyHandle(){
}
public MyHandle(Looper looper){
super(looper);
}
public void handleMessage(Message msg){
String str=msg.getData().getString("name");
String strps=msg.getData().getString("password");
MyMessage message=new MyMessage();
message.setb((byte)1);
message.setUsername(str);
message.setPassword(strps);
try {
connect.sendBuffer.clear();
connect.sendBuffer.put(message.Message2Byte());
connect.sendBuffer.flip();
connect.socketChannel.write(connect.sendBuffer);
} catch (Exception e) {

e.printStackTrace();
}
}
}

}

服务器代码

package mytcp;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;

public class NioServer {

/**
* @param args
*/
private int port = 20001;
final makeFlagFalse timerFlag = new makeFlagFalse();
static makeFlagFalse loginLoopBoolean = new makeFlagFalse();
private static ByteBuffer sBuffer = ByteBuffer.allocate(1024);
private static ByteBuffer rBuffer = ByteBuffer.allocate(1024);
private static Map<SocketChannel, Integer> clientsMap = new HashMap<SocketChannel, Integer>();
private Selector selector = null;
private ServerSocketChannel serverSocketChannel = null;
private Object gate = new Object();

public NioServer(int port) {
this.port = port;
try {
init();
} catch (Exception e) {
e.printStackTrace();
}
}

public static void main(String[] args) throws InterruptedException, IOException {
final NioServer server = new NioServer(20001);
Thread accept = new Thread() {
public void run() {
server.accept();
}
};

accept.start();
while (loginLoopBoolean.flag == true)
server.loginService();
server.gamePlay(clientsMap);
}

public void init() throws IOException {
selector = Selector.open();
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().setReuseAddress(true);
// serverSocketChannel.configureBlocking(false);
serverSocketChannel.socket().bind(new InetSocketAddress(port));
System.out.println("服务器启动");
}

public void accept() {
while (true) {
try {
SocketChannel socketChannel = serverSocketChannel.accept();
System.out.println("receive the connection from "
+ socketChannel.socket().getInetAddress() + ":"
+ socketChannel.socket().getPort());

socketChannel.configureBlocking(false);
synchronized (gate) {
selector.wakeup();
socketChannel.register(selector, SelectionKey.OP_READ);
}
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
System.out.println("Damn it");
}
}
}

public void loginService() throws InterruptedException {


synchronized (gate) {
}
try {
int n = selector.select();
if (n == 0){}
else{
Set<SelectionKey> selectionKeys = selector.selectedKeys();
for (SelectionKey key : selectionKeys) {
try {
if (key.isReadable()) {
handle_receive_login(key);
}
} catch (Exception e) {
try {
if (key != null) {
key.cancel();
key.channel().close();
}
} catch (Exception ex) {
e.printStackTrace();
}
}
}
selectionKeys.clear();
}
} catch (Exception e) {
e.printStackTrace();
}

}

public void handle_receive_login(SelectionKey key) {
SocketChannel socketChannel = null;
ServerMessage message = null;
ServerMessage sendMessage = new ServerMessage();
socketChannel = (SocketChannel) key.channel();
rBuffer.clear();
try {
int count = socketChannel.read(rBuffer);
if (count > 0) {
rBuffer.flip();
message = ServerMessage.byte2Message(rBuffer.array());
System.out.println("Receive from"+ socketChannel.socket().getInetAddress() + " : "+ message.getb());
switch(message.getb()){
case(1):
int valid = DB.idCheck(message.getUsername(),
message.getPassword());
sendMessage.setb((byte) 2);
sendMessage.setValid(valid);
sendMes sendMes = new sendMes(sendMessage, socketChannel);
sendMes.send();

break;
case(2):
break;
case (3):
if(timerFlag.flag){
if(message.getReady() == 1){
if(clientsMap.size() < 6){
clientsMap.put(socketChannel, clientsMap.size() + 1);
sendMessage.setb((byte) 3);
sendMessage.setReady(1);
sendMes sendMes1 = new sendMes(sendMessage, socketChannel);
sendMes1.send();
}

else{
sendMessage.setb((byte) 3);
sendMessage.setReady(0);
sendMes sendMes1 = new sendMes(sendMessage, socketChannel);
sendMes1.send();
}

Timer timer = new Timer();

System.out.println("flag is " + timerFlag.flag);
TimerTask task = new TimerTask(){
public void run(){
timerFlag.falsify();
System.out.println("flag now is " + timerFlag.flag);
}
};
timer.schedule(task, 20*1000);
}
}else{
sendMessage.setb((byte) -1); /*-1 implies that game is currently in progress*/
sendMes sendMes1 = new sendMes(sendMessage, socketChannel);
sendMes1.send();
}
break;

case (4):
if(timerFlag.flag == true){
sendMessage.setb((byte) -2); /*send message saying "waiting for other players*/
sendMes sendMes1 = new sendMes(sendMessage, socketChannel);
sendMes1.send();
}else{
loginLoopBoolean.falsify();
}
break;
}
}/*end of if(count=0)*/
} catch (Exception e) {
e.printStackTrace();
key.cancel();
try {
socketChannel.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}

}


public void gamePlay(Map<SocketChannel, Integer> clientsMap) throws IOException, InterruptedException{
Dealer dealer = new Dealer();
dealer.createDeck();
ServerMessage sendMessage = new ServerMessage();

if(!clientsMap.isEmpty()){
Set<SocketChannel> clientSet = clientsMap.keySet();
Iterator<SocketChannel> iterator=clientSet.iterator();
SocketChannel currentPlayer;
while(iterator.hasNext()){
currentPlayer=iterator.next();
sendMessage.setb((byte) 4);
sendMessage.setCard1(dealer.dealCard(dealer.deck));
sendMessage.setCard2(dealer.dealCard(dealer.deck));
sendMes sendMes1 = new sendMes(sendMessage, currentPlayer);
sendMes1.send();
}
//send who's turn it is
loginService();
}
}

public static class makeFlagFalse{
boolean flag;
public makeFlagFalse() {
this.flag = true;
}
public void falsify(){
flag = false;
}
public void makeTrue(){
flag = true;
}
}

public class sendMes{
ServerMessage message;
SocketChannel currentPlayer;

sendMes(ServerMessage message,SocketChannel currentPlayer){
this.message = message;
this.currentPlayer=currentPlayer;
}
public void send() throws IOException{
sBuffer.clear();
sBuffer.put(message.Message2Byte());
sBuffer.flip();
currentPlayer.write(sBuffer);
}
}


}

我很感激任何形式的帮助。

谢谢

最佳答案

private Object gate = new Object(); 

它应该是不稳定的

关于java - Android NIO 服务器选择器在没有消息发送时读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17853017/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com