最近由于工作需要,需要在建立android app和Linux app 之间建立多对一网络连接,网络是wifi p2p 的。
android app 作为网络的服务器端,它主要包含两个模块,
1、ReceiveServer ,它主要创建服务器端和管理客户端连接
2、SourceListener,它主要对客户端的抽象,代表一个客户端连接
Linux app 作为网络连接的客户端,他只有一个模块
SenderService ,它主要连接到网络,并收发数据
一、在android app 端建立网络服务器以及多个客户端的管理
ReceiveServer 是服务器管理模块,监听客户端连接
private class ReceiveServer implements Runnable {
private static final int RECEIVE_SERVER_DEFAULT_PORT = 7238; //端口号
private static final int RECEIVE_SERVER_MAX_CONNECTIONGS = 16; //最多连接数
private ServerSocket mServer; //建立android 服务器用
private Thread mThread; //server 活动处理线程
private ExecutorService mThreadPool; //客户端线程集合
private ReceiveServer(){
}
private boolean start() {
if(mThread != null){
return false;
}
try{
mServer = new ServerSocket(RECEIVE_SERVER_DEFAULT_PORT);
}catch (IOException ex) {
Log.w(TAG, "Failure to open receive Server" + ex);
return false;
}
mThread = new Thread(this,TAG);
mThreadPool = Executors.newFixedThreadPool(RECEIVE_SERVER_MAX_CONNECTIONGS);
mThread.start();
return true;
}
private boolean stop(){
if(mThread != null){
mThread.interrupt();
if(mThreadPool != null){
try{
mThreadPool.shutdownNow();
}catch (SecurityException e) {
Log.w(TAG, "Could not stop all threads");
}
}
mThread = null;
mThreadPool = null;
try {
mServer.close();
mServer = null;
return true;
} catch (IOException e) {
Log.w(TAG, "Could not close the server");
}
}
return false;
}
public void run(){
if (DBG) Log.d(TAG,"Thread running");
try{
if(DBG) Log.d(TAG,"mServer is " + mServer.toString() +
"local address is " + InetAddress.getLocalHost().getHostAddress());
}catch (IOException ex) {
Log.w(TAG, "Failure to open receive Server" + ex);
}
while(Thread.currentThread() == mThread){
if(DBG) Log.d(TAG, "Thread.currentThread() == mThread");
try{
Socket client = mServer.accept(); //收到client响应
if(mThreadPool != null){
mThreadPool.submit(new SourceListener(client)); //启动该客户端处理的线程,并将该线程加入到mThreadPool中
}else {
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}catch (Exception e) {
Log.w(TAG, "mServer.accept error: ", e);
}
}
}
}
SourceListener是客户端管理模块
private class SourceListener implements Runnable{
private Socket mClient;
private String mMac;
private OutputStream mOut;
private InputStream mIn;
SourceListener(Socket client){
mClient = client;
try{
mIn = mClient.getInputStream();
mOut = mClient.getOutputStream();
}catch(IOException e){
e.printStackTrace();
}
}
public void run(){
if(DBG) Log.d(TAG,"SourceListener run");
try{
byte data[] = CMD_READY.getBytes();
mOut.write(data);
if(DBG) Log.d(TAG,"send Ready to client");
byte[] buf = new byte[64];
int len;
len = mIn.read(buf);
if(DBG) Log.d(TAG, "len is " + len + buf);
final String request = new String(buf);//mDataIn.readLine();
String command;
String mac;
String ip;
if(DBG) Log.d(TAG, "Read from source is " + request);
String parms[] = request.split(" ");
if(parms.length != 4)
return;
command = parms[0];
mac = parms[1];
ip = parms[2];
if(command.equals(START_PLAY_CMD)){
sendPlayWfdBroadcast(mac,ip);
}
}catch(IOException e) {
Log.w(TAG, "read Line error " + e);
}finally {
if(DBG) Log.d(TAG, "Do nothing");
}
}
}
二、在Linux app 中建立客户端。
#include "SenderService.h"
#define RECEIVE_SERVER_DEFAULT_PORT 7238 //端口
#define START_PLAY_CMD "START_WFD"
#define SERVER_IP_ADDR "192.168.49.1"
namespace android {
SenderService::SenderService(const char* mac){
mSockets = -1;
mSendAgain = false;
memset(mMac, 0, sizeof(mMac));
if(mac != NULL){
memcpy(mMac,mac, strlen(mac));
}
}
SenderService::~SenderService(){}
status_t SenderService::createClient(const char * sourceHost){
status_t err = OK;
int32_t sourcePort = RECEIVE_SERVER_DEFAULT_PORT;
if(sourceHost == NULL)
return -1;
memset(mIP, 0, sizeof(mIP));
memcpy(mIP,sourceHost,sizeof(mIP));
mSockets = socket(AF_INET,SOCK_STREAM, 0);
if (mSockets < 0){
err = -errno;
return err;
}
struct sockaddr_in addr;
memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
addr.sin_family = AF_INET;
struct hostent *ent= gethostbyname(SERVER_IP_ADDR);
if (ent == NULL) {
err = -h_errno;
close(mSockets);
return err;
}
addr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
addr.sin_port = htons(sourcePort);
in_addr_t x = ntohl(addr.sin_addr.s_addr);
ALOGD("connecting to %d.%d.%d.%d:%d",
(x >> 24),
(x >> 16) & 0xff,
(x >> 8) & 0xff,
x & 0xff,
ntohs(addr.sin_port));
//连接服务器
int res = connect(mSockets, (const struct sockaddr *)&addr, sizeof(addr));
if(res < 0)
return res;
ALOGD("connected ");
return err;
}
//像服务器发送数据
int SenderService::writeData(){
int size;
memset(mSenderBuf, 0, sizeof(mSenderBuf));
sprintf(mSenderBuf,"%s %s %s end",START_PLAY_CMD,mMac,mIP);
ALOGD("SEND to Recever %s",mSenderBuf);
do{
size = send(mSockets, mSenderBuf, sizeof(mSenderBuf),0);
ALOGD("Send size is %d",size);
}while(size < 0 && errno == EINTR);
if(size < 0){
ALOGE("Send failed");
}
return size;
}
//从服务器端读取数据
status_t SenderService::readData(){
ssize_t size;
memset(mReceiveBuf,0, sizeof(mReceiveBuf));
struct sockaddr_in remoteAddr;
socklen_t remoteAddrLen = sizeof(remoteAddr);
do{
size = recvfrom(mSockets, mReceiveBuf, sizeof(mReceiveBuf),0,
(struct sockaddr *)&remoteAddr, &remoteAddrLen);
}while(size < 0 && errno == EINTR);
uint32_t connect_ip = ntohl(remoteAddr.sin_addr.s_addr);
ALOGD("Receive from %u.%u.%u.%u is %s" ,
connect_ip >> 24,
(connect_ip >> 16) & 0xff,
(connect_ip >> 8) & 0xff,
connect_ip & 0xff,mReceiveBuf);
return OK;
}
//分析从服务器端读取数据
int SenderService::parseData(){
if(strstr(mReceiveBuf, "Ready")){
sp<AMessage> msg = new AMessage(kWhatSendData, id());
msg->post();
}else if(strstr(mReceiveBuf, "Echo")){
mSendAgain = false;
}
return 0;
}
void SenderService::start(){
sp<AMessage> msg = new AMessage(kWhatReadData, id());
msg->post();
}
//
void SenderService::onMessageReceived(
const sp<AMessage> &msg) {
status_t ret;
ALOGD(" [%s %d] msg->what:%d", __FUNCTION__,__LINE__,msg->what());
switch(msg->what()){
case kWhatReadData:
ret = readData();
if(ret == OK){
parseData();
}
break;
case kWhatSendData:{
writeData();
}
break;
default:
ALOGE("Unknow cmd %d",msg->what());
break;
}
}