android Linux 网络连接

本文详细介绍了如何在Android应用作为服务器端与Linux应用作为客户端之间建立WiFi P2P网络连接,包括服务器端的多客户端管理与客户端的连接与数据收发过程。

 最近由于工作需要,需要在建立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;
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值