- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用 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/
我花了相当多的时间尝试优化文件哈希算法,以尽可能地提高性能。 查看我之前的 SO 主题: Get File Hash Performance/Optimization FileChannel Byte
我不太明白它们之间有什么不同,所以我对这两个包有一些疑问。 在 Google 上浏览了一下之后,似乎 Oracle 决定使用更新和增强的 NIO.2 包来更新 NIO 包,作为 JDK7 版本的一部分
在 Java 1.4 之前,通过在不同的输入流/输出流之间移动字节来处理文件是常见的做法。 自 Java 1.4 起,其中 NIO已添加,建议使用 Channels 执行相同操作。 与 NIO2在 J
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and th
我需要重写一些应该在 Java 6 VM 上运行的 Java 7 文件 IO 代码。 该实现使用了方便的 Java 7 功能,例如自动关闭、Paths 和 Files。 更具体地说,我需要处理像 /t
当我查看java中Scanner的源代码时,我发现一些让我困惑的事情 import java.nio.file.Path; import java.nio.*; 它们之间有什么区别,为什么它们不直接导
我的 Java 代码中几乎所有文件 I/O 操作都使用 java.nio.*。然而,在今天调试一段代码时,我注意到调试器 (Intellij IDEA 14) 显示了以下关于 java.nio.fil
奇怪的是,我无法在 Google 中找到 NIO.2 异步 IO 性能与通过 java.nio.channels.Selector 使用 NIO 的多路复用 IO 的明确答案。 所以,我的问题是:NI
我是初级 Java 程序员。 今天,我练习了如何在 java 中复制文件并尝试按照本教程进行操作 http://www.journaldev.com/861/4-ways-to-copy-file-i
我有一个指向绝对路径的 java.nio.Path: /home/user/project/resources/configuration.xml 我有第二个 java.nio.Path 指向项目的根
我开始使用java.nio.*,现在我想知道:为什么java.nio.Paths.get(..)不使用java.nio.Path 对象作为输入? 现在我总是做这样的事情: final Path bas
我是新手,正在学习 Java。我尝试在 Netbeans 7 中运行以下应用程序。 import java.io.*; import java.nio.file.*; import java.nio.
我的 Java 程序(见下文)有时会在 java.nio.File.move() 方法执行中因 java.nio.file.AccessDeniedException 崩溃。 我不明白为什么会抛出这个
所以我在这里阅读我最喜欢的软件模式书籍之一(面向模式的软件架构 - 并发和网络对象的模式),特别是关于 Proactor/Reactor 异步 IO 模式的部分。我可以看到通过使用可选 channel
我有一个方法如下,它已经正常运行了很长时间: private String loadFromFile(){ RandomAccessFile inFile = null; FileCh
我在 IntellijIDEA Community Edition 2017.3 版本中收到以下错误。该项目使用java版本“1.8.0-ea”。请给我一些解决问题的想法 Error:Internal
一 点睛 在 scatter-and-gather 场景下,可以将数据写入多个 Buffer 中。在 NIO 中,也能够同时操作多个缓冲区。在很多 Channel 实现类中,都提供了多个重载的 rea
I/O简介 在 Java 编程中,直到最近一直使用 流 的方式完成 I/O。所有 I/O 都被视为单个的字节的移动,通过一个称为 Stream 的对象一次移动一个字节。流 I/O 用于与外部世界接
一 点睛 给某一个文件加锁,防止并发访问时引起的数据不安全。 在 JUC 中,可以使用 synchronized、Lock 给共享的资源加锁,或者使用 volatile、CAS 算法等防止并发冲突。在
一 点睛 给某一个文件加锁,防止并发访问时引起的数据不安全。 在 JUC 中,可以使用 synchronized、Lock 给共享的资源加锁,或者使用 volatile、CAS 算法等防止并发冲突。在
我是一名优秀的程序员,十分优秀!