Home >Database >Mysql Tutorial >cocos2d-x 基于BSD Socket网络通讯模块

cocos2d-x 基于BSD Socket网络通讯模块

WBOY
WBOYOriginal
2016-06-07 15:32:061404browse

1. 预备知识: 线程,互斥锁,信号量: // 创建一个线程 int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)( void ), void *restrict arg); // 初始化互斥量 int pthread_mutex_init(pthread_mutex_t *mut

1. 预备知识:

线程,互斥锁,信号量: 

 <span>//</span><span>创建一个线程 </span>
 <span>int</span> pthread_create(pthread_t *restrict tidp, <span>const</span> pthread_attr_t *restrict attr, <span>void</span> *(*start_rtn)(<span>void</span>), <span>void</span> *restrict arg);
<span>//</span><span>初始化互斥量</span>
 <span>int</span> pthread_mutex_init(pthread_mutex_t *mutex, <span>const</span> pthread_mutex-attr_t *mutexattr);
<span>//</span><span>给互斥量上锁</span>
<span>int</span> pthread_mutex_lock(pthread_mutex_t *mutex);
<span>//</span><span>给互斥量解锁</span>
<span>int</span> pthread_mutex_unlock(pthread_mutex_t *mutex);
<span>//</span><span>信号量初始化</span>
<span>int</span> sem_init(sem_t *sem, <span>int</span> pshared, unsigned <span>int</span> value);
<span>//</span><span>发送信号量</span>
<span>int</span> sem_post(sem_t *sem);
<span>//</span><span>等待信号量</span>
<span>int</span> sem_wait(sem_t *sem);

注意:cocos2d-x引擎,已经内置pthread库,如下加入条件编译即可:

#ifdef WIN32
#include "../../cocos2dx/platform/third_party/win32/pthread/pthread.h"
#else
#include "pthread.h"
#endif // WIN32


本项目TCP用的是ODSocket,直接加入ODSocket.h,ODSocket.cpp到工程目录即可。


顺便提一下通用的BSD Socket: :

<span>//</span><span>创建一个socket连接</span>
<span>int</span> socket (<span>int</span> family, <span>int</span> type, <span>int</span> protocol);
<span>//</span><span>连接目标主机</span>
<span>int</span> connect(<span>int</span> s, <span>const</span> <span>struct</span> sockaddr *name, <span>int</span> namelen);
<span>//</span><span>关闭socket连接</span>
 <span>int</span> close(<span>int</span> fildes);
<span>//</span><span>发送内容</span>
ssize_t send(<span>int</span> s, <span>const</span> <span>void</span> *msg, size_t len, <span>int</span> flags);
<span>//</span><span>接收内容</span>
ssize_t recv(<span>int</span> s, <span>void</span> *buf, size_t len, <span>int</span> flags);


udp部分,使用通用的socket :

#ifdef WIN32
#include <winsock2.h>	
typedef int	socklen_t;
#endif

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)//android 平台,注意包含"cocos2d.h"
#include <android>
#define LOGI(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOG_TAG "JWYGC_Thread"

#include <sys>
#include <netinet>
#include <netdb.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys>
#include <sys>
#include <arpa>
#include <errno.h>
typedef int	SOCKET;</errno.h></arpa></sys></sys></unistd.h></fcntl.h></netdb.h></netinet></sys></android></winsock2.h>

2. WIN32平台注意事项

1) 在链接器加入附加依赖项pthreadVCE2.lib.

2) 用以下代码对网络进行初始化,退出时进行清除.

<span>//</span><span>初始化, 放在网络使用之前</span>
WSADATA wsaData;
WSAStartup(MAKEWORD(<span>2</span>, <span>0</span>), &wsaData)

<span>//</span><span>清除网络使用, 放在网络使用完毕之后.</span>
WSACleanup()

3) 线程使用需要初始化, 退出时进行清除.

<span>//线程使用之前,</span><span>初始化线程</span>
pthread_win32_process_attach_np();  
<span>//线程使用之后,</span><span>清除线程使用</span>
pthread_win32_process_detach_np();

4) windows关闭连接使用closesocket,安卓和ios使用close.

#ifdef WIN32
closesocket(new_socket);
#else
close(new_socket); // android ,ios平台
#endif

5) 解析IP地址时,使用inet_addr, 详细如下:

<span>const</span> <span>char</span> *addr = <span>"</span><span>192.168.1.1</span><span>"</span>;
<span>struct</span> in_addr ip = {<span>0</span>};
<span>#ifdef</span> WIN32 
ip.s_addr = inet_addr(addr);
<span>if</span>(ip.s_addr == INADDR_NONE)
{
    CCLOG(<span>"</span><span>can't parse IP address %s</span><span>"</span>, addr);        
}
<span>#else</span> 
<span>if</span> (!inet_aton(addr, &ip))
{
    CCLOG(<span>"</span><span>can't parse IP address %s</span><span>"</span>, addr);
}
<span>#endif</span>
<span>struct</span> hostent *host;
host = gethostbyaddr((<span>char</span> *) &ip, <span>4</span>, AF_INET);

6) 判断主机连接是否关闭, 在此模块中本人使用recv返回值来判断连接是否被主机关闭, Win32和其他平台迥异的是recv返回0为主机关闭连接, 而其他平台(ios, android)返回-1为主机关闭连接.


3. ios平台注意事项

 1) 调试发现, ios平台sem_init总是返回-1, 网上求证得知可能由于ios不支持无名信号量导致, 使用以下方式用以代替sem_init.

<span>//</span><span>获取及初始化信号量</span>
sem_t *my_sem;
my_sem = sem_open(<span>"</span><span>/mysem1</span><span>"</span>, O_CREAT,<span>0664</span>,<span>0</span>);

<span>//</span><span>使用sem_open方式创建的信号量在使用完毕需清除.</span>
sem_unlink(<span>"</span><span>/mysem1</span><span>"</span>);

4. android平台注意事项

1)记得在AndroidManifest.xml中加上网络使用权限.

<span><span>uses-permission </span><span>android:name</span><span>=”android.permission.INTERNET”></span><span></span></span>

<span>给出几个小函数:</span>
<span>1,获取本机IP:</span>
<pre class="brush:php;toolbar:false">bool UdpSocket::getLocalIP(char *szLocalIP)
{
#ifdef	WIN32
	char name[255];//定义用于存放获得的主机名的变量 
	struct hostent *hostinfo;
	if( gethostname ( name, sizeof(name)) == 0) {
		if((hostinfo = gethostbyname(name)) != NULL) {
			strcpy(szLocalIP,inet_ntoa (*(struct in_addr *)*hostinfo->h_addr_list));
			strcpy(m_szLocalIP,szLocalIP);
		}
	}
	return true;
#else
	int sock_get_ip;   
	struct   sockaddr_in *sin;  
	struct   ifreq ifr_ip; 
	if ((sock_get_ip=socket(AF_INET, SOCK_STREAM, 0)) == -1) {  
		CCLOG("get_ip error");
		return false;  
	}  


	memset(&ifr_ip, 0, sizeof(ifr_ip));     
	strncpy(ifr_ip.ifr_name, "wlan0", sizeof(ifr_ip.ifr_name) - 1);     //无线是wlan0,有线是eth0。可能还需要判断有线无线,比较麻烦。
	if( ioctl( sock_get_ip, SIOCGIFADDR, &ifr_ip) sin_addr));            
	close( sock_get_ip );       
	strcpy(m_szLocalIP,szLocalIP);
	return true;
#endif
}





Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn