⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 netsocket.c

📁 netsocket——深入研究BREW手机游戏开发Chapter10
💻 C
📖 第 1 页 / 共 2 页
字号:
            else
				DisplayOutput (pMe, 1, "No Data!");
		}
		break;
	case USAGE_SOCKET_READ:
	case USAGE_SOCKET_READBALE:
		{
            int rv;
			uint32 uTime;
            char szBuf[50] = {0};
            rv = ISOCKET_Read(piSock, (byte*)&uTime, sizeof(uint32));
            if (rv == AEE_NET_WOULDBLOCK) {
				DisplayOutput (pMe, 1, "Waiting...      ");
				ISOCKET_Readable(piSock, CommonReadCB, (void*)pMe);
				return;
            } 
            else if (rv == AEE_NET_ERROR) 
				DisplayOutput (pMe, 1, "Read Error!");
            else if (rv > 0) {
				//此函数用于将传递的无符号长整型值从网络字节顺序转换为主机字节顺序。
				uTime = NTOHL(uTime) ;
				DisplayOutput(pMe,0,"Seconds elapsed since Jan");
				SPRINTF(szBuf, "1, 1900  =  %lu", (long) uTime);
				DisplayOutput (pMe, 1, szBuf);
            }
			//此时表示rv返回值为0
            else
				DisplayOutput (pMe, 1, "No Data!");
		}
		break;
	case USAGE_SOCKET_READV:
	case USAGE_SOCKET_WRITEV:
		{
            int32 rv;
            char szBuf[100] = {0};     
            SockIOBlock iov[2] = {0};
            byte buf1[6] = {0};
            byte buf2[6] = {0};
            int16 iovcount = 2;
			
            iov[0].pbBuffer = buf1;
            iov[0].wLen = 5;
            iov[1].pbBuffer = buf2;
            iov[1].wLen = 5;
			
            ISOCKET_Readable(piSock, CommonReadCB, (void*)pMe);
            rv = ISOCKET_ReadV(piSock, iov, iovcount);
            if (rv == AEE_NET_WOULDBLOCK) {
				DisplayOutput (pMe, 1, "Waiting...");
				ISOCKET_Readable(piSock, CommonReadCB, (void*)pMe);
				return;
            } 
            else if (rv == AEE_NET_ERROR) 
				DisplayOutput (pMe, 1, "Read Error!");
            else if (rv > 0) {
				SPRINTF(szBuf, "Buff1 = %s", iov[0].pbBuffer);
				DisplayOutput (pMe, 5, szBuf);
				SPRINTF(szBuf, "Buff2 = %s", iov[1].pbBuffer);
				DisplayOutput (pMe, 6, szBuf);
            }
			//rv==0时候的情况,即没有可读的数据
            else
				DisplayOutput (pMe, 1, "No Data!");
		}
		break;
	case USAGE_SOCKET_SENDTO:
	case USAGE_SOCKET_RECVFROM:
		{
            int rv;
            char psz [100] = {0};
            INAddr addr;
            uint16 port;
			
			//此函数始终立即返回读取的字节数。如果没有数据包到达而套接字
			//仍处于有效状态,ISOCKET_RecvFrom() 将返回AEE_NET_WOULDBLOCK。
			//ISOCKET_Readable()可用于接收再次尝试ISOCKET_RecvFrom() 的通知。
            rv = ISOCKET_RecvFrom (piSock, (byte *)psz, sizeof (psz), 0, &addr, &port);
            if (rv == AEE_NET_WOULDBLOCK) {
				DisplayOutput (pMe, 1, "Waiting...");
				ISOCKET_Readable(piSock, CommonReadCB, (void*)pMe);
				return;
            } 
            else if (rv == AEE_NET_ERROR) 
				DisplayOutput (pMe, 1, "Read Error!");
            else if (rv > 0)
				DisplayOutput (pMe, 1, psz);
            else
				DisplayOutput (pMe, 1, "No Data!");
		}
		break;
	default:
		break;
   }
}

/*!
 *		@brief:		写回调函数
 *		@para:		pUser指向用户的指针
 */
void CommonWriteCB(void *pUser)
{
	int iRetValue;
	CNetSocket *pme = (CNetSocket*)pUser;
	switch(pme->APIFnType) {

	//如果绑定还没有完成,那么继续进行
	case USAGE_SOCKET_BIND:
		if ((iRetValue = ISOCKET_Bind (pme->pISocket, AEE_INADDR_ANY, 1240))
			== AEE_NET_WOULDBLOCK)
			ISOCKET_Writeable(pme->pISocket, CommonWriteCB, (void *)pme);
		else
			if (iRetValue != AEE_NET_SUCCESS)
				DisplayOutput (pme, 1, "Bind Failed.");
			else
				DisplayOutput (pme, 1, "Bind Succeeded.");
			break;
			
	case USAGE_SOCKET_WRITE:
	case USAGE_SOCKET_WRITEABLE:
		{
            int  rv;
            char pszData[100] = "Data Written and Read from Remote Host echo-port..";
            char *psz = NULL;
            int  cbWrite;
			
            psz = pszData;
            cbWrite = STRLEN (pszData);

            while (cbWrite > 0) {
				//写函数不能注册回调,直接返回成功写入的字节数,如果未能写入字符
				//则立即返回AEE_NET_WOULDBLOCK,于是可以通过ISOCKET_Writeable函
				//数再注册一个回调,等到合适时再写
				rv = ISOCKET_Write(pme->pISocket, (byte *)psz, (uint16)cbWrite);
				if (rv == AEE_NET_WOULDBLOCK) {
					//循环注册回调的用法
					ISOCKET_Writeable(pme->pISocket, CommonWriteCB, (void *)pme);
					return;
				} 
				else if (rv == AEE_NET_ERROR)
					return;
				cbWrite -= rv;
				psz += rv;
            }
            CommonReadCB((void *)pme);
		}
		break;

		
	case USAGE_SOCKET_WRITEV:
		{
            int rv = 0;
            SockIOBlock iov[2];
            uint16 wiovcount = 2;
			
            iov[0].pbBuffer = (byte *)"data1";
            iov[0].wLen  = 5;
            iov[1].pbBuffer = (byte *)"data2";
            iov[1].wLen =5;
			
			rv = ISOCKET_WriteV(pme->pISocket, iov, wiovcount);
			
            if (rv == AEE_NET_ERROR)
				return;
			//回调的循环注册,保证最终读写成功
			else if (rv == AEE_NET_WOULDBLOCK) {
				ISOCKET_Writeable(pme->pISocket, CommonWriteCB, (void *)pme); 
				return;
            }
            else if (rv > 0)
				CommonReadCB ((void *)pme);
		}
		break;
		
	case USAGE_SOCKET_SENDTO:
	case USAGE_SOCKET_RECVFROM:
		
		break;

	default:
		break;
	}
}

/*!
 *		@brief:		连接回调函数
 *		@para:		pme指向用户的指针
 *		@para:		wParam传递某些数值参数
 */
static void ConnectCBFun(CNetSocket *pme , int wParam)
{
	if(wParam != AEE_NET_SUCCESS) {
		int lastError;
		char psz[50];
		if (wParam != AEE_NET_WOULDBLOCK) {
			//函数ISOCKET_GetLastError不能注册回调,直接返回值
			lastError = ISOCKET_GetLastError(pme->pISocket);
			if(lastError == AEE_NET_EISCONN) {
				DisplayOutput(pme,2,"ERROR!");
				DisplayOutput(pme,3,"The Net Has Connected!");
			}
			else {
				SPRINTF(psz, "ERROR Number : %u",lastError);
				DisplayOutput(pme, 2, psz);
			}
		}
		else
			DisplayOutput(pme, 2, "ERROR: NET_WOULDBLOCK");
		return;
	}
	else
		DisplayOutput(pme,5,"Succeed!");

//	ISOCKET_Cancel(pme->pISocket,ConnectCBFun,NULL);
	switch(pme->APIFnType) {
		
	case USAGE_BASIC_USAGE:
//		CommonReadCB(pme);
		break;
	
	case USAGE_SOCKET_GETPEERNAME:
		{
            int iRetValue = AEE_NET_EBADF;
            INAddr inAddr;
            uint16 pwPort;
            char psz[50] = {0};
			
			//此函数用于返回对等端的IP 地址和端口,例如,最近与该
			//套接字通信的实体的IP地址,返回地址通过一个传入的指针
			//参数来返回,函数执行情况可以立即返回。
            if (AEE_NET_SUCCESS != (iRetValue = ISOCKET_GetPeerName
				(pme->pISocket, &inAddr, &pwPort))) {
				int nErroNo;
                DisplayOutput (pme, 1, "GetPeerName Failed");
				nErroNo = ISOCKET_GetLastError(pme->pISocket);
				SPRINTF(psz,"The Erro No:%d",nErroNo);
				DisplayOutput(pme,2,psz);

			}
			else {
				ConvertToIPAddr(inAddr, psz);
				DisplayOutput (pme, 3, psz);
			}
		}
		break;
		
	case USAGE_SOCKET_WRITE:
	case USAGE_SOCKET_WRITEABLE:
		CommonWriteCB((void *)pme);
		break;
	
	case USAGE_SOCKET_READV:
	case USAGE_SOCKET_WRITEV:
		{
            int rv = 0;
            SockIOBlock iov[2];
            uint16 wiovcount = 2;
			
            iov[0].pbBuffer = (byte *)"data1";
            iov[0].wLen  = 5;
            iov[1].pbBuffer = (byte *)"data2";
            iov[1].wLen =5;
			
			//对于AEE_SOCK_STREAM (TCP) 套接字,独立调用ISOCKET_Write()的
			//行为会有所不同,因为多次调用ISOCKET_Write() 会产生一些不必要
			//的TCP 数据包。对于AEE_SOCK_DGRAM (UDP) 套接字,独立缓冲区可作
			//为单独数据包来处理。
			//此函数始终立即返回成功写入的字节数。如果未能写入字节而连接仍然
			//有效,ISOCKET_Write() 将返回AEE_NET_WOULDBLOCK。要得到再次调用
			//ISOCKET_WriteV() 的时间通知,调用程序必须调用ISOCKET_Writeable()。
			rv = ISOCKET_WriteV(pme->pISocket, iov, wiovcount);
			
			//出错
			if (rv == AEE_NET_ERROR)
				return;
			//返回成功读写的字节数
            else if (rv > 0)
				CommonReadCB ((void *)pme);
			//阻塞,调用ISOCKET_Writeable函数来注册回调
            else if (rv == AEE_NET_WOULDBLOCK) {
				ISOCKET_Writeable(pme->pISocket, CommonWriteCB, (void *)pme);
				return;
            }
		}		
		break;
	
	case USAGE_SOCKET_READ:
	case USAGE_SOCKET_READBALE:
		CommonReadCB ((void*)pme);
		break;

	default:
		break;
	}
}


/*!
 *		@brief:		域名解析回调函数
 *		@para:		pUser指向用户的指针
 */
void GetHostByNameCB(void * pUser)
{
	CNetSocket * pMe = (CNetSocket*)pUser;
	char *szMsg = MALLOC(100);

	if(!szMsg)
		return;
	
	switch(pMe->dnsresult.nResult)
	{
	case AEE_NET_BADDOMAIN:
		SPRINTF(szMsg,"Host name is mal-formed; not a valid host name");
		break;
	case AEE_NET_UNKDOMAIN: 
		SPRINTF(szMsg,"Unknown host, or one without IP addresses");
		break;
	case AEE_NET_ETIMEDOUT:
		SPRINTF(szMsg,"No response was seen within the maximum time limit");
		break;
	case EUNSUPPORTED:
		SPRINTF(szMsg,"No DNS servers are configured");
		break;
	case ENOMEMORY: 
		SPRINTF(szMsg,"Could not perform query due to allocation failure");
		break;
	default:
		if(pMe->dnsresult.nResult > 0)
            SPRINTF(szMsg,"Success.Obtained %d address(es)",pMe->dnsresult.nResult);
		else
            SPRINTF(szMsg,"Unknown Error");
		break;
	}
	
	DisplayOutput(pMe, 1, szMsg);
	if(pMe->dnsresult.nResult > 0 && pMe->dnsresult.nResult <= AEEDNSMAXADDRS)      
	{
		int i = 0;
		char psz[50];
		for( ; i < pMe->dnsresult.nResult ; i ++) {
			ConvertToIPAddr(pMe->dnsresult.addrs[i],psz);
			DisplayOutput(pMe, i + 2, psz);
		}
	}
	
	FREE(szMsg);
	return;
}

/*!
 *		@brief:		显示状态函数
 *		@para:		pMe指向CSound结构的指针
 *		@para:		pszStr指向要显示的字符串的指针
 *		@para:		line表示要从第几行开始显示
 */
void DisplayOutput(CNetSocket * pMe, int line , char *pszStr)
{
	AECHAR * pszBuf = NULL;

	if ((pszBuf = (AECHAR *)MALLOC(200)) == NULL)
		return;
	
	STR_TO_WSTR ((char *)pszStr, pszBuf, 200);
	
	IDISPLAY_DrawText(pMe->a.m_pIDisplay, AEE_FONT_NORMAL, pszBuf,-1, 0, 20*line, NULL, IDF_ALIGN_CENTER);
	IDISPLAY_Update(pMe->a.m_pIDisplay);

	FREE (pszBuf);
	return;   
}

/*!
 *		@brief:		转换IP地址
 *		@para:		psz指向IP地址字符串的指针
 */
INAddr ConvertToINAddr(char *psz)
{
	INAddr ul = 0;
	int nByte = 0;
	char c;
	
	if(!psz)
		return 0;
	
	while (ISDIGIT(*psz)) {
		int n = 0;
		while ( ISDIGIT(c=*psz)) {
			n = n*10 + (c - '0');
			++psz;
		}
		((char*)&ul)[nByte++] = n;
		
		if (nByte == 4 || *psz != '.')
			break;
		
		++psz;
	}
	
	if (nByte < 4 || ISALNUM(*psz))
		ul = 0xFFFFFFFF;
	return ul;
}

/*!
 *		@brief:		转换IP地址
 *		@para:		psz指向IP地址字符串的指针
 */
void ConvertToIPAddr(INAddr inaddr, char *psz)
{
	int i;
	int x[4] = {0};
	char ch[30];
	char ch1[50];
	
	for (i = 0; i < 4; i++) {
		x[i] = (int)(inaddr & 0xff);
		inaddr = inaddr >> 8;     
	}
	for (i = 3; i >= 0; i--) {
		SPRINTF (ch,"%d",x[i]);
		if (i != 0)
			STRCAT (ch, ".");
		if (i == 3)
			STRCPY (ch1, ch);
		else
			STRCAT(ch1, ch);
	}
	STRCPY (psz, ch1);   
}

/*!
 *		@brief:		创建菜单
 *		@para:		pMe指向用户结构的指针
 */
void BuildMainMenu(CNetSocket *pMe)
{
	AEERect qrc;
	AEEDeviceInfo di;
	AECHAR szBuf[100] = {0};
	
	//设置标题
	STR_TO_WSTR("INet-ISocket Funcs:", szBuf, sizeof(szBuf));
	IMENUCTL_SetTitle(pMe->pIMenuCtl, NULL, 0, szBuf);
	
	//设置菜单边框
	ISHELL_GetDeviceInfo(pMe->a.m_pIShell,&di);
	qrc.x = 0;
	qrc.y = 0;
	qrc.dx = di.cxScreen;
	qrc.dy = di.cyScreen;
	IMENUCTL_SetRect(pMe->pIMenuCtl, &qrc);  
	
	//为菜单加条目
	STR_TO_WSTR("1. Basic Usage", szBuf, sizeof(szBuf));
	IMENUCTL_AddItem(pMe->pIMenuCtl, 0, 0, USAGE_BASIC_USAGE, szBuf, 0);
	
	STR_TO_WSTR("2. Net: GetHostByName", szBuf, sizeof(szBuf));
	IMENUCTL_AddItem(pMe->pIMenuCtl, 0, 0, USAGE_NET_GETHOSTBYNAME, szBuf, 0);

	STR_TO_WSTR("3. Net: GetLastError", szBuf, sizeof(szBuf));
	IMENUCTL_AddItem(pMe->pIMenuCtl, 0, 0, USAGE_NET_GETLASTERROR, szBuf, 0);

	STR_TO_WSTR("5. Net: SetLinger", szBuf, sizeof(szBuf));
	IMENUCTL_AddItem(pMe->pIMenuCtl, 0, 0, USAGE_NET_SETLINGER, szBuf, 0);

	STR_TO_WSTR("6. Net: NetStatus", szBuf, sizeof(szBuf));
	IMENUCTL_AddItem(pMe->pIMenuCtl, 0, 0, USAGE_NET_NETSTATUS, szBuf, 0);	

	STR_TO_WSTR("7. Net: GetMyIPAddr", szBuf, sizeof(szBuf));
	IMENUCTL_AddItem(pMe->pIMenuCtl, 0, 0, USAGE_NET_GETMYIPADDRESS, szBuf, 0);	

	STR_TO_WSTR("8. SKT: GetPeerName", szBuf, sizeof(szBuf));
	IMENUCTL_AddItem(pMe->pIMenuCtl, 0, 0, USAGE_SOCKET_GETPEERNAME, szBuf, 0);	

	STR_TO_WSTR("11. SKT: Bind", szBuf, sizeof(szBuf));
	IMENUCTL_AddItem(pMe->pIMenuCtl, 0, 0, USAGE_SOCKET_BIND, szBuf, 0);	

	STR_TO_WSTR("12. SKT: Write", szBuf, sizeof(szBuf));
	IMENUCTL_AddItem(pMe->pIMenuCtl, 0, 0, USAGE_SOCKET_WRITE, szBuf, 0);	

	STR_TO_WSTR("13. SKT: WriteV", szBuf, sizeof(szBuf));
	IMENUCTL_AddItem(pMe->pIMenuCtl, 0, 0, USAGE_SOCKET_WRITEV, szBuf, 0);	

	STR_TO_WSTR("14. SKT: Read", szBuf, sizeof(szBuf));
	IMENUCTL_AddItem(pMe->pIMenuCtl, 0, 0, USAGE_SOCKET_READ, szBuf, 0);	

	STR_TO_WSTR("15. SKT: ReadV", szBuf, sizeof(szBuf));
	IMENUCTL_AddItem(pMe->pIMenuCtl, 0, 0, USAGE_SOCKET_READV, szBuf, 0);	

	STR_TO_WSTR("16. SKT: SendTo", szBuf, sizeof(szBuf));
	IMENUCTL_AddItem(pMe->pIMenuCtl, 0, 0, USAGE_SOCKET_SENDTO, szBuf, 0);	

	STR_TO_WSTR("17. SKT: RecvFrom", szBuf, sizeof(szBuf));
	IMENUCTL_AddItem(pMe->pIMenuCtl, 0, 0, USAGE_SOCKET_RECVFROM, szBuf, 0);	

	STR_TO_WSTR("18. SKT: Readable", szBuf, sizeof(szBuf));
	IMENUCTL_AddItem(pMe->pIMenuCtl, 0, 0, USAGE_SOCKET_READBALE, szBuf, 0);	

	STR_TO_WSTR("19. SKT: Writeable", szBuf, sizeof(szBuf));
	IMENUCTL_AddItem(pMe->pIMenuCtl, 0, 0, USAGE_SOCKET_WRITEABLE, szBuf, 0);	

	STR_TO_WSTR("20. SKT: Cancel", szBuf, sizeof(szBuf));
	IMENUCTL_AddItem(pMe->pIMenuCtl, 0, 0, USAGE_SOCKET_CANCEL, szBuf, 0);	

	
	//激活菜单
	IMENUCTL_SetActive(pMe->pIMenuCtl,TRUE);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -