android Linux 网络连接

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

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

 最近由于工作需要,需要在建立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、付费专栏及课程。

余额充值