两个android手机通信,Rosmin--两台Android手机的Socket双向通信

这篇博客介绍了如何使用Socket在两台Android设备间实现双向通信,以此控制一个小车。通过一台手机获取摄像头和传感器数据作为服务器,另一台手机作为客户端发送控制指令。详细阐述了客户端如何连接服务器,接收陀螺仪和磁力计角度,以及如何发送控制命令。同时,服务器端如何接受并同时发送数据,确保双向通信的实现。整个过程中,使用了Handler来处理数据流,避免了潜在的bug。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上学期搞定了小车,现在终于结束了大机器人,趁还没真正进入考研复习的高潮赶紧把以前的代码整理整理。

先讲讲我们那小车,2台手机+车体组成。一个手机放车上作为server,用其摄像头、陀螺仪、磁力计来获取图像、确定小车方向。另一台手机负责控制,作为client,并画出小车行进图。如何从server获取陀螺仪、磁力计角度,又如何把client的控制命令发送给server就成了一个问题。这里我们使用socket双向通信。

先讲client部分

// Socket Client connect to Server

connectButton.setOnClickListener(newButton.OnClickListener()

{

@Override

publicvoidonClick(View v)

{

// TODO Auto-generated method stub

try

{

ip = mEditText02.getText().toString();

Thread thread = newThread(newmSocketConnectRunnable2());

thread.start();

//          thread.sleep(100);

goToControl();           //进行控制命令的处理

connectButton.setVisibility(View.INVISIBLE);

mEditText02.setVisibility(View.INVISIBLE);

}

catch(Exception e)

{

e.printStackTrace();

}

}

});

两台手机都连接到同个wifi,这个就不多讲了。首先你得有个EditText填写server的IP地址,然后有个按钮,点击启动个线程,负责与server通信,这里传给Thread的构造函数调用Runnable接口。socket其实就是对某一个服务器的一个端口进行连接,连接上后就形成会话。由于这里socket是全双向的字节流,所以连上的时候其本身就已经具备了双向通信能力。

然后我们看它调用的接口,怎么连接和接受server发来的数据……

//Socket Client

publicclassmSocketConnectRunnable2implementsRunnable

{

@Override

publicvoidrun()

{

try

{

mSocket02 = newSocket(ip, intSocketServerPort);

if(mSocket02.isConnected())

{

Log.i(TAG, "Socket Client is connected to Server.");

strTemp01="Socket Client is connected to Server.";

}

BufferedReader br = newBufferedReader(newInputStreamReader(mSocket02.getInputStream()));

while(true)

{

strTemp01 = br.readLine();

if(!strTemp01.isEmpty())

handler.post(rReceiveInfo);

}

}

catch(Exception e)

{

if(bIfDebug)

{

Log.e(TAG, e.toString());

e.printStackTrace();

}

}

}

}

ip上面说了,intSocketServerPort是socket端口,我这里设置为8080。mSocket02就像个水管,可以往里灌水也可以抽水。这里通过BufferedReader获得字节流,用handler传递进行数据处理。这里推荐用handler,不仅增加代码可度性,更容易避免莫名其妙的bug……

以上是建立socket连接并且从server获取字节流的过程,下面是发送字节流的部分……

publicstaticvoidaction(String a){

//当Socket连接正常且不为空时,流输出给server

if(mSocket02!=null&& mSocket02.isConnected() && !a.equals(""))

{

try

{

bw = newBufferedWriter(newOutputStreamWriter(mSocket02.getOutputStream()));

bw.write(a+"\n");

bw.flush();

}

catch(Exception e)

{

Log.e(TAG, e.toString());

e.printStackTrace();

}

}

}

这里,比如我用 action("forward"),则字节流将forward发往server,至于这里流输出,不过多解释,详细的需要自己仔细查看socket。

然后是server部分……这里我们设置一个按钮用于开启socket server

// Run Socket Server

mButton01.setOnClickListener(newButton.OnClickListener()

{

@Override

publicvoidonClick(View v)

{

// TODO Auto-generated method stub

mButton01.setEnabled(false);

mButton02.setEnabled(true);

setContentView(R.layout.i3);

Thread thread = newThread(newmSocketConnectRunnable1());

thread.start();

}

});

这里也是用Thread的构造函数调用Runnable接口

//Socket Server

publicclassmSocketConnectRunnable1implementsRunnable

{

@Override

publicvoidrun()

{

// TODO Auto-generated method stub

try

{

mServerSocket01 = newServerSocket(intSocketServerPort);

mServerSocket01.setReuseAddress(true);

Log.i(TAG, strDebugPreFix+"Socket Server is Running: "+intSocketServerPort);

while(!mServerSocket01.isClosed())

{

mSocket01 = mServerSocket01.accept();

Thread read = newThread(newRunnable()

{

BufferedReader br = newBufferedReader(newInputStreamReader(mSocket01.getInputStream()));

@Override

publicvoidrun()

{

try

{

while(mSocket01.isConnected())

{

msg = br.readLine();

Handler01.post(rManualControl);

}

}

catch(Exception e)

{

if(bIfDebug)

{

Log.e(TAG, e.toString());

e.printStackTrace();

}

}

}

});

read.start();

//在接受数据的同时发送数据,实现双向通信

Thread write = newThread (newRunnable()

{

@Override

publicvoidrun()

{

while(mSocket01.isConnected())

{

try

{

Thread.sleep(100);

}

catch(InterruptedException e)

{

// TODO Auto-generated catch block

e.printStackTrace();

}

Handler01.post(rSendStr);

}

}

});

write.start();

}

}

catch(Exception e)

{

if(bIfDebug)

{

Log.e(TAG, e.toString());

e.printStackTrace();

}

}

}

}

publicRunnable rSendStr =newRunnable(){

publicvoidrun()

{

try

{

BufferedWriter bw = newBufferedWriter(newOutputStreamWriter(mSocket01.getOutputStream()) );

strMove = strMoveFlag

+ " "+ String.valueOf((int) gyrAngle)

+ " "+ String.valueOf( ( ((int)corrected_a) +((accX>3)?90:180) )%360)//由于小车姿态问题,需要进行修正

+ " "+ strQR

+" \n";

bw.write(strMove);

bw.flush();

strQR = "0";// accX>3

}

catch(IOException e)

{

// TODO Auto-generated catch block

e.printStackTrace();

}

}

};

这里用了read write两个thread,分别负责流输入和流输出。这里唯独要提的就是write部分,加上sleep控制流输出频率,不然会造成堵塞。将BufferedWriter通过handler放到Runnable中解决莫名其妙的问题(我的基础不行……惭愧惭愧……)。

PS:用handler解决部分问题,多亏了队友sununs11.这里是我们组项目中截下的代码,会有很多无关于本文双向通信的代码,请无视……后续会放出全部代码与代码解释……这代码是干什么的???请看这个简短视频:基于OpenCV和Android的语音物标识别车

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值