- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
事情就是这样。我想使用 Android 实现多人 Tic Tac Toe。我使用 Java 部署了多线程服务器,但我在客户端方面遇到了困难。据我所知,您应该使用后台线程来处理通信,并将 UI 线程留给 UI 内容。我在开发游戏循环和线程通信时遇到一些问题。我决定使用 Handlers 而不是 AsyncTask。
我认为循环应该在后台线程中实现,看起来有点像这样:使用 Handler 从 UI 获取信息将数据写入输出流到服务器从服务器的输入流中读取数据处理数据使用其他Handler将数据发送到UI。
我正在使用 Eclipse 和模拟器作为客户端对此进行测试。问题是我无法设置处理程序。 UIHandler 的一个处理程序作为参数发送到 ClientThread Constructut,Net Handler 是通过一种方法从 Client 线程获取到 UIThread 中。
我读到我需要使用Looper来处理传入的数据。我不能无限循环地调用handleMessage方法吗?我非常不知道如何部署它。如果有任何想法,我将不胜感激。
主要 Activity 客户端类:
package com.example.tictactoecliet;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.StrictMode;
import android.os.StrictMode.ThreadPolicy;
import android.util.Log;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.RadioButton;
import android.widget.TextView;
import android.widget.ViewFlipper;
public class MainActivity extends Activity implements OnClickListener,
ClientVocabulary {
private static final String TAG = MainActivity.class.getSimpleName();
private Socket client;
private PrintWriter pw;
private EditText etIp;
private TextView tvStatus;
private Button bCon;
private Socket socket;
PrintWriter out;
private BufferedReader in;
private RadioButton rbVsPlayer, rbVsAI;
private ViewFlipper vF;
private ClientThread cT;
private ImageButton[][] board = new ImageButton[5][5];
private Handler h, clientHandler;
SocketAddress sockaddr;
/******************************************************************************************/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
setupUIHandler();
try {
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*****************************************
* initialize
*
* @return nothing ffs
******************************************/
private void init() {
etIp = (EditText) findViewById(R.id.etIP);
tvStatus = (TextView) findViewById(R.id.tvStatus);
rbVsAI = (RadioButton) findViewById(R.id.rbAI);
rbVsPlayer = (RadioButton) findViewById(R.id.rb2players);
bCon = (Button) findViewById(R.id.bCon);
//
// // listeners
//
vF = (ViewFlipper) findViewById(R.id.vF);
bCon.setOnClickListener(this);
board[0][0] = (ImageButton) findViewById(R.id.iB_1A);
board[0][1] = (ImageButton) findViewById(R.id.iB_2A);
board[0][2] = (ImageButton) findViewById(R.id.iB_3A);
board[0][3] = (ImageButton) findViewById(R.id.iB_4A);
board[0][4] = (ImageButton) findViewById(R.id.iB_5A);
board[1][0] = (ImageButton) findViewById(R.id.iB_1B);
board[1][1] = (ImageButton) findViewById(R.id.iB_2B);
board[1][2] = (ImageButton) findViewById(R.id.iB_3B);
board[1][3] = (ImageButton) findViewById(R.id.iB_4B);
board[1][4] = (ImageButton) findViewById(R.id.iB_5B);
board[2][0] = (ImageButton) findViewById(R.id.iB_1C);
board[2][1] = (ImageButton) findViewById(R.id.iB_2C);
board[2][2] = (ImageButton) findViewById(R.id.iB_3C);
board[2][3] = (ImageButton) findViewById(R.id.iB_4C);
board[2][4] = (ImageButton) findViewById(R.id.iB_5C);
board[3][0] = (ImageButton) findViewById(R.id.iB_1D);
board[3][1] = (ImageButton) findViewById(R.id.iB_2D);
board[3][2] = (ImageButton) findViewById(R.id.iB_3D);
board[3][3] = (ImageButton) findViewById(R.id.iB_4D);
board[3][4] = (ImageButton) findViewById(R.id.iB_5D);
board[4][0] = (ImageButton) findViewById(R.id.iB_1E);
board[4][1] = (ImageButton) findViewById(R.id.iB_2E);
board[4][2] = (ImageButton) findViewById(R.id.iB_3E);
board[4][3] = (ImageButton) findViewById(R.id.iB_4E);
board[4][4] = (ImageButton) findViewById(R.id.iB_5E);
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
board[i][j].setOnClickListener(this);
}// end of inner for
}// end of outer for
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case (R.id.bCon):
vF.showNext();
blockAllTile();
cT = new ClientThread((short) (rbVsPlayer.isChecked() ? 2:1), clientHandler, etIp.getText().toString());
cT.start();
break;
case (R.id.iB_1A):
sendLocation(0);
break;
case (R.id.iB_2A):
sendLocation(1);
break;
case (R.id.iB_3A):
sendLocation(2);
break;
case (R.id.iB_4A):
sendLocation(3);
break;
case (R.id.iB_5A):
sendLocation(4);
break;
case (R.id.iB_1B):
sendLocation(5);
break;
case (R.id.iB_2B):
sendLocation(6);
break;
case (R.id.iB_3B):
sendLocation(7);
break;
case (R.id.iB_4B):
sendLocation(8);
break;
case (R.id.iB_5B):
sendLocation(9);
break;
case (R.id.iB_1C):
sendLocation(10);
break;
case (R.id.iB_2C):
sendLocation(11);
break;
case (R.id.iB_3C):
sendLocation(12);
break;
case (R.id.iB_4C):
sendLocation(13);
break;
case (R.id.iB_5C):
sendLocation(14);
break;
case (R.id.iB_1D):
sendLocation(15);
break;
case (R.id.iB_2D):
sendLocation(16);
break;
case (R.id.iB_3D):
sendLocation(17);
break;
case (R.id.iB_4D):
sendLocation(18);
break;
case (R.id.iB_5D):
sendLocation(19);
break;
case (R.id.iB_1E):
sendLocation(20);
break;
case (R.id.iB_2E):
sendLocation(21);
break;
case (R.id.iB_3E):
sendLocation(22);
break;
case (R.id.iB_4E):
sendLocation(23);
break;
case (R.id.iB_5E):
sendLocation(24);
break;
}
}
public void unblockAllTile(){
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
board[i][j].setEnabled(true);
}// end of inner for
}//
}
public void sendLocation(int location){
}
public void blockAllTile(){
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
board[i][j].setEnabled(false);
}// end of inner for
}// end of outer for
}
private void setupUIHandler(){
h = new Handler(){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
Bundle b = msg.getData();
String content = b.getString("msg");
if(content.equals(KKIP_ALL_CONNECTED)){
tvStatus.setText(KKIP_ALL_CONNECTED);
}else{
Log.i("i no noł", "i no noł");
}
}
};
}
}
后台线程:
package com.example.tictactoecliet;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
public class ClientThread extends Thread implements ClientVocabulary {
private Socket socket;
private short game_mode;
private Handler uiHandler;
private Handler netHandler;
private Bundle inMsgBundle, outMsgBundle;
private final static String TAG = ClientThread.class.getSimpleName();
private BufferedReader in;
private String ip, serverResponse;
PrintWriter out;
public ClientThread(Short game_mode, Handler h, String ip) {
this.game_mode = game_mode;
this.uiHandler = h;
this.ip = ip;
inMsgBundle = new Bundle();
outMsgBundle = new Bundle();
}
@Override
public void run() {
// TODO Auto-generated method stub
Log.i("Thread started",TAG);
connectionSetup();
Log.i("Setup connection",TAG);
Looper.prepare();
setupHandler();
Log.i("Handler set",TAG);
try {
play();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Looper.loop();
}// end of run
public Handler getHandlerToMsgQueue() {
while (netHandler == null) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return netHandler;
}
// //////////////////////////////////////////
public void connectionSetup() {
try {
Log.i("Setup start",TAG);
InetAddress serverAddress = InetAddress.getByName(ip);
SocketAddress sockaddr = new InetSocketAddress(serverAddress, 4321);
// socket = new Socket("192.168.0.102",4321);
socket = new Socket();
socket.connect(sockaddr);
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream())), true);
out.println(game_mode);
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
Log.i("Setup finish",TAG);
} catch (Exception e) {
e.printStackTrace();
}
}
////////////////
public void setupHandler(){
Log.i("Handler ready",TAG);
netHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
notifyAll();
}
};
Log.i("Handler done",TAG);
}
///////////////////////////play//////////////////////////
public void play() throws Exception{
String response;
Log.v("Play start", "Play start");
try {
response =null;
if(in.readLine()!=null){
response=in.readLine();
Log.v(response, response);
}else{
Log.v(TAG, "Resposne is empty");
}
if( response.startsWith(KKIP_WELCOME)){
Log.i("wow welcome so much", "so much welcome");
char mark = response.charAt(8);
}else if (response.startsWith(KKIP_WAITING_FOR_OPPONENT)){
while (true){
//updatuj status zegarem, może wait i notify?
if(response.startsWith(KKIP_ALL_CONNECTED)){
Log.v("now we play","play");
sendMessageToUI(KKIP_ALL_CONNECTED);
response=in.readLine();
if(response.startsWith(KKIP_VALID_MOVE)){
//update board
}else if (response.startsWith(KKIP_MOVED)){
int loc = Integer.parseInt(response.substring(15));
//update board
}else if (response.startsWith(KKIP_VICTORY)){
}else if(response.startsWith(KKIP_DEFEAT)){
}else if (response.startsWith(KKIP_TIE)){
}
}
}//end of while (true)
//end of if connected
}
out.print(KKIP_QUIT);
}
catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
finally{
socket.close();
}
}
private void sendMessageToUI(String msg){
Bundle data = new Bundle();
data.putString("msg", msg);
Message m = new Message();
m.setData(data);
uiHandler.sendMessage(m);
}
}
代码尚未完成,因此某些方法可能看起来很奇怪。我有兴趣解决 UIThread 到 BackGroundThread 到服务器的通信。没有别的了。
最佳答案
Handler
对象隐式绑定(bind)到在创建它们的Thread
中运行的Looper
。您的后台线程需要创建自己的Looper
(或使用HandlerThread
为您处理Looper
。)然后您的后台线程需要将其 Handler
传回主 UI 线程。
关于java - Android TCP/IP 和 GUI 到其他线程的通信 - Tic Tac Toe 多人游戏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20998977/
我是 ZMQ 的新手。我发现 ZMQ 套接字实现比 winsock 简单得多。但我怀疑 “使用 ZMQ TCP 套接字创建的客户端可以与传统的 TCP 服务器通信吗?” 换句话说我的 ZMQ 客户端可
我想使用 TCP 协议(protocol) 将数据发送到 Logstash。为了发送数据,我正在使用 Node-RED。一个简单的配置如下所示: 在 Logstash 文件夹中,我创建了一个名为 no
当我尝试更改窗口缩放选项时,作为 root,我可以通过在 /proc/sys/net/中执行 net.ipv4.tcp_mem=16777000 来更改值。如果我必须更改这 100 个系统,那将需要大
明天做一些练习题,这道做不出来 TCP 服务器连接 TCP 客户端进行通信所需的最小套接字端口数是多少? 肯定只有两个吧?一个用于服务器,一个用于客户端,但这似乎是显而易见的。我的伙伴们认为 TCP
考虑一个存在一个服务器和多个客户端的场景。每个客户端创建 TCP 连接以与服务器交互。 TCP alive的三种用法: 服务器端保活:服务器发送 TCP 保活以确保客户端处于事件状态。如果客户端死了,
TCP TAHOE 和 TCP RENO 有什么区别。 我想知道的是关于 3-dup-ack 和超时的行为? SST 发生了什么变化? 谢谢! 最佳答案 TCP Tahoe 和 Reno 是处理 TC
大家早上好。我一直在阅读(其中大部分在堆栈溢出中)关于如何进行安全密码身份验证(散列 n 次,使用盐等)但我怀疑我将如何在我的 TCP 客户端中实际实现它-服务器架构。 我已经实现并测试了我需要的方法
在遍历 RFC793 时,我开始知道应该以这种方式选择初始序列号段重叠被阻止。 有人能解释一下如果发生重叠,重复段将如何影响 TCP? 最佳答案 不同的操作系统有不同的行为。参见 http://ins
你能举例说明一下tcp/ip中nagle算法的概念吗? 最佳答案 我认为Wikipedia在开头的段落中做得很好。 Nagle's document, Congestion Control in IP
似乎最大 TCP 接收窗口大小为 1GB(使用缩放时)。因此,仍然可以用一个连接填充 100Gb 管道的最大 RTT 是 40ms(因为 2 * 40E-3 * 100E9/8 = 1GB)。这会将这
考虑在两个 TCP 端点之间建立的 TCP 连接,其中一个调用: 关闭():此处,不允许进一步读取或写入。 关机(fd,SHUT_WR):这会将全双工连接转换为单工连接,其中调用 SHUT_WR 的端
我是在 Lua 中编写解析器的新手,我有两个简短的问题。我有一个包含 TCP 选项的数据包,如 MSS、TCP SACK、时间戳、NOP、窗口比例、未知。我基本上是在尝试剖析 TCP 选项字段中的未知
TCP 是否不负责通过在传输过程中发生丢失等情况时采取任何可能必要的措施来确保通过网络完整地发送流? 它做的不对吗? 为什么更高的应用层协议(protocol)及其应用程序仍然执行校验和? 最佳答案
考虑使用 10 Mbps 链路的单个 TCP (Reno) 连接。假设此链路不缓冲数据并且接收方的接收缓冲区比拥塞窗口大得多。设每个 TCP 段的大小为 1500 字节,发送方和接收方之间连接的双向传
考虑这样一个场景,有client-a和server-b。 server-b 禁用了 TCP keepalive。 server-b 没有任何应用程序逻辑来检查 TCP 连接是否打开。 client-a
我正在尝试用 Rust 编写回显服务器。 use std::net::{TcpStream, TcpListener}; use std::io::prelude::*; fn main() {
听说对于TCP连接,服务器会监听一个端口,并使用另一个端口发送数据。 例如,Web 服务器监听端口 80。每当客户端连接到它时,该服务器将使用另一个端口(比如 9999)向客户端发送数据(Web 内容
我试图了解带有标记 PSH 和标记 URG 的 TCP 段之间的区别。我阅读了 RFC,但仍然无法理解,其中一个在将数据发送到进程之前缓冲数据而另一个没有吗? 最佳答案 它们是两种截然不同的机制。 #
有第三方服务公开 TCP 服务器,我的 Node 服务器(TCP 客户端)应使用 tls Node 模块与其建立 TCP 连接。作为 TCP 客户端, Node 服务器同时也是 HTTP 服务器,它应
我正在发送一些 TCP SYN 数据包以获得 TCP RST 的返回。为了识别每个探测器,我在 TCP 序列字段中包含一个计数器。我注意到以下几点: 当SYN probe中的sequence numb
我是一名优秀的程序员,十分优秀!