[转]UDP/TCP穿越NAT的P2P通信方法研究(UDP/TCP打洞 Hole Punching) - Leo.W - 博客园.
UDP/TCP 打洞(穿越NAT)技术 - wenhuiqiao的专栏 - 博客频道 - CSDN.NET
zz 内网与外网通信 内网与内网通信 NAT_noob_百度空间
首先要知道内网地址是不能直接和外网通信的。这里就牵涉到了一个NAT协议。现在用的最多的是NAT的一种NAPTNetwork Address/Port Translator的技术。 简单来说NAPT就是:当你与外网建立连接时,本地IP为192.168.0.11:4000,要与外网202.160.4.40:3300建立连接。NAT做的工作就是把本地地址映射成为外网地址(想连上internet都得至少有个外网IP)如外网IP为202.202.202.202,那么NAT就把它映射为202.202.202.202:5000(端口号随机的)。那么连接就变为202.202.202.202:5000到 202.160.4.40:3300。那么如果Server发送来的包就又被NAT逆向转换为内网IP。就可以通信了。 当然其他IP如果向202.202.202.202:5000发送信息是会被丢弃的,如何连接呢? 这就是内网与内网通信 这里需要一个Server,两方都登陆,Server记录下a,b双方的IP。a,b双方都能和Server通信,那么a,b怎么通信呢,这就需要神奇的打洞技术。a欲发信息与b,a把此事告知中间人S,S转告b,由于匿名的IP会被b丢弃,所以,要把a的地址变为不是匿名。所以b向a的地址发送信息(此为打洞),显然连不上,但是网关却记录下了a的地址,此时a再发信息到b就搞定了。反过来就能发信息给a,因此连接建立!a—>b? a->s s->b b->a? a->b ok!
入手mac mini
到香港玩,顺便买了个mac mini ,4688港币,比内地便宜个800块,加8g内存,买了个无线逻辑270鼠标套装 共530 ,入手一个24寸的三星显示器,1399
总价:5800
接下来准备做ios开发。
要学习的东西真多啊,看了好几本opengl es的书,html5游戏开发以及3D方便的基础教程。路漫漫其修远兮!
mac lion 小技巧
光盘引导————开机按住C键 U盘引导——–开机按住OPTION键(也是ALT键)
制作MAC OS X LION的U盘启动或光盘安装(收集整理)
1.下载LION。(3.74G) 注意:先不要安装LION,安装完后安装包会自动删除~ (如果你已经升级到了 Lion,只能重新下载的话,苹果会告诉你已经安装了系统,也就是说不能直接下载,解决这个问题的办法是在 Mac App Store 中按住 option 键点击安装,这样就可以跳过版本检查下载 Lion 安装程序。)—来自 applefans2008 大大,感谢
2. 右键你刚下载的LION—显示安装包内容—进入「SharedSupport」—可以看到「InstallESD.dmg」
3.另外再打开—-「应用程序」——「实用工具」——「磁盘工具」—把 InstallESD.dmg 拖到磁盘工具窗口左边的空白处
4.插入U盘 (最好5G以上) 或光盘(DVD) 以下就以U盘为例,光盘直接刻录,很简单
5.在 「磁盘工具」中 选中你的U盘—-点击「分区」标签—格式选择「Mac OS 扩展(日志式)」—点「选项」—–选择「CUID 分区表」—-好—-应用
6.分区完后~~ 点「恢复」标签—-把左边 的「InstallESD.dmg」 拖到 「源磁盘」那里,自动识别地址然后点「恢复」~~~~~~等待吧,颤抖吧~~
zz 利用C++试用JSON第三方库JsonCpp - 51CTO.COM
利用C++试用JSON第三方库JsonCpp - 51CTO.COM.
本文选择第三方库JsonCpp来解析json,JsonCpp是比较出名的c++解析库,在json官网也是首推的。
JSON是一个轻量级的数据定义格式,比起XML易学易用,而扩展功能不比XML差多少,用之进行数据交换是一个很好的选择
JSON的全称为:JavaScript Object Notation ,顾名思义,JSON是用于标记javascript对象的,详情参考http://www.json.org/。
本文选择第三方库JsonCpp来解析json,JsonCpp是比较出名的c++解析库,在json官网也是首推的。
JsonCpp简介
JsonCpp主要包含三种类型的class:Value Reader Writer。
jsoncpp中所有对象、类名都在namespace json中,包含json.h即可。
注意: Json::Value只能处理ANSI类型的字符串,如果C++程序使用Unicode编码的,最好加一个Adapt类来适配。
下载和编译
本文运行环境是: Redhat 5.5 + g++version 4.6.1 + GNU Make 3.81 + jsoncpp-0.5.0
下载地址是:http://sourceforge.net/projects/jsoncpp/
解压之后得到jsoncpp-src-0.5.0文件夹,我们只需要jsoncpp的头文件和cpp文件,其中jsonscpp的头文件位于jsoncpp-src-0.5.0includejson,jsoncpp的cpp文件位于jsoncpp-src-0.5.0srclib_json。
这里我列出我们的工作目录:
jsoncpp/ //工作目录
|-- include //头文件根目录
| |-- json //json头文件,对应jsoncpp-src-0.5.0includejson
|-- src //cpp源码文件根目录
|-- json //jsoncpp源码文件,对应jsoncpp-src-0.5.0srclib_json
|-- main.cpp //我们的主函数,调用jsoncpp的示例代码
|-- makefile //makefile,不用我们多说了吧,不懂请看我博客的makefile最佳实践
反序列化Json对象
假设有一个json对象如下:
- {
- "name": "json″,
- "array": [
- {
- "cpp": "jsoncpp"
- },
- {
- "java": "jsoninjava"
- },
- {
- "php": "support"
- }
- ]
- }
我们要实现这个json的反序列号代码如下:
- voidreadJson() {
- usingnamespacestd;
- std::stringstrValue = "{\"name\":\"json\",\"array\":[{\"cpp\":\"jsoncpp\"},{\"java\":\"jsoninjava\"},{\"php\":\"support\"}]}";
- Json::Reader reader;
- Json::Value value;
- if(reader.parse(strValue, value))
- {
- std::stringout= value["name"].asString();
- std::cout <<out<<std::endl;
- constJson::Value arrayObj = value["array"];
- for(unsigned inti = 0;i <arrayObj.size(); i++)
- {
- if(!arrayObj[i].isMember("cpp"))
- continue;
- out= arrayObj[i]["cpp"].asString();
- std::cout <<out;
- if(i != (arrayObj.size() - 1))
- std::cout <<std::endl;
- }
- }
- }
序列化Json对象
- voidwriteJson() {
- usingnamespacestd;
- Json::Value root;
- Json::Value arrayObj;
- Json::Value item;
- item["cpp"] = "jsoncpp";
- item["java"] = "jsoninjava";
- item["php"] = "support";
- arrayObj.append(item);
- root["name"] = "json";
- root["array"] = arrayObj;
- root.toStyledString();
- std::stringout= root.toStyledString();
- std::cout <<out<<std::endl;
- }
完整代码下载
下载之后,执行以下命令
unzip jsoncpp.zip
cd jsoncpp
make
./main
原文:http://www.cnblogs.com/ggjucheng/archive/2012/01/03/2311107.html
zz OPhone 3D开发之射线拾取 - 技术文章 - OPhone SDN [OPhone 开发者网络]
OPhone 3D开发之射线拾取 - 技术文章 - OPhone SDN [OPhone 开发者网络].
在前两篇介绍OPhone 3D开发的文章中,我们着重介绍了OPhone平台中强大的3D渲染API。在本文中,我们将通过编写一个触摸屏幕拾取3D空间图元的小程序,来向大家展示如何在OPhone中处理2D屏幕空间与3D世界的交互,并附带介绍包围体、几何相交检测等其他相关知识。程序最终的效果如图1所示,选中的三角形呈现红色半透明,深红色点表示当前屏幕触摸位置:

什么是拾取

- /**
- * 更新拾取射线
- * @param screenX - 屏幕坐标X
- * @param screenY - 屏幕坐标Y
- */
- public static void update(float screenX, float screenY) { AppConfig.gMatView.fillFloatArray(AppConfig.gpMatrixViewArray);
- //由于OpenGL坐标系原点为左下角,而窗口坐标系原点为左上角
- //因此,在OpenGl中的Y应该需要用当前视口高度,减去窗口坐标Y
- float openglY = AppConfig.gpViewport[3] - screenY;
- //z = 0 , 得到P0
- gProjector.gluUnProject(screenX, openglY, 0.0f, AppConfig.gpMatrixViewArray, 0,
- AppConfig.gpMatrixProjectArray, 0, AppConfig.gpViewport, 0, gpObjPosArray, 0);
- //填充射线原点P0
- gPickRay.mvOrigin.set(gpObjPosArray[0], gpObjPosArray[1], gpObjPosArray[2]);
- //z = 1 ,得到P1
- gProjector.gluUnProject(screenX, openglY, 1.0f, AppConfig.gpMatrixViewArray, 0,
- AppConfig.gpMatrixProjectArray, 0, AppConfig.gpViewport, 0, gpObjPosArray, 0);
- //计算射线的方向,P1 - P0
- gPickRay.mvDirection.set(gpObjPosArray[0], gpObjPosArray[1], gpObjPosArray[2]);
- gPickRay.mvDirection.sub(gPickRay.mvOrigin);
- //向量归一化
- gPickRay.mvDirection.normalize();
- }
- /**
- * 模拟实现GLU.gluLookAt()函数,参数相同,将计算结果矩阵返回
- * @param eye
- * @param center
- * @param up
- * @param out - 返回的计算结果矩阵
- */
- public static void gluLookAt(Vector3f eye, Vector3f center, Vector3f up, Matrix4f out) {
- tmpF.x = center.x - eye.x;
- tmpF.y = center.y - eye.y;
- tmpF.z = center.z - eye.z;
- tmpF.normalize();
- tmpUp.set(up);
- tmpUp.normalize();
- tmpS.cross(tmpF, tmpUp);
- tmpT.cross(tmpS, tmpF);
- out.m00 = tmpS.x;
- out.m10 = tmpT.x;
- out.m20 = -tmpF.x;
- out.m30 = 0;
- out.m01 = tmpS.y;
- out.m11 = tmpT.y;
- out.m21 = -tmpF.y;
- out.m31 = 0;
- out.m02 = tmpS.z;
- out.m12 = tmpT.z;
- out.m22 = -tmpF.z;
- out.m32 = 0;
- out.m03 = 0;
- out.m13 = 0;
- out.m23 = 0;
- out.m33 = 1;
- tmpMat.setIdentity();
- tmpMat.setTranslation(-eye.x, -eye.y, -eye.z);
- out.mul(tmpMat);
- }
- /**
- * 模拟实现GLU.gluPersective()函数,参数相同,将计算结果填入返回矩阵中
- * @param fovy
- * @param aspect
- * @param zNear
- * @param zFar
- * @param out - 计算结果返回
- */
- public static void gluPersective(float fovy, float aspect, float zNear, float zFar, Matrix4f out) {
- float sine, cotangent, deltaZ;
- float radians = (float)(fovy / 2 * Math.PI / 180);
- deltaZ = zFar - zNear;
- sine = (float)Math.sin(radians);
- if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) {
- return;
- }
- cotangent = (float)Math.cos(radians) / sine;
- out.setIdentity();
- out.m00 = cotangent / aspect;
- out.m11 = cotangent;
- out.m22 = - (zFar + zNear) / deltaZ;
- out.m32 = -1;
- out.m23 = -2 * zNear * zFar / deltaZ;
- out.m33 = 0;
- }
- //设置投影矩阵
- float ratio = (float) width / height;//屏幕宽高比
- gl.glMatrixMode(GL10.GL_PROJECTION);
- gl.glLoadIdentity();
- //GLU.gluPerspective(gl, 45.0f, ratio, 1, 5000);系统方式
- Matrix4f.gluPersective(45.0f, ratio, 1, 5000, AppConfig.gMatProject);
- gl.glLoadMatrixf(AppConfig.gMatProject.asFloatBuffer());
- //设置视图矩阵
- gl.glMatrixMode(GL10.GL_MODELVIEW);
- gl.glLoadIdentity();
- //GLU.gluLookAt(gl, mfEyeX, mfEyeY, mfEyeZ, mfCenterX, mfCenterY, mfCenterZ, 0, 1, 0);//系统方式
- Matrix4f.gluLookAt(mvEye, mvCenter, mvUp, AppConfig.gMatView);
- gl.glLoadMatrixf(AppConfig.gMatView.asFloatBuffer());
- /**
- * 射线与模型的精确碰撞检测
- * @param ray - 转换到模型空间中的射线
- * @param trianglePosOut - 返回的拾取后的三角形顶点位置
- * @return 如果相交,返回true
- */
- public boolean intersect(Ray ray, Vector3f[] trianglePosOut) {
- boolean bFound = false;
- //存储着射线原点与三角形相交点的距离
- //我们最后仅仅保留距离最近的那一个
- float closeDis = 0.0f;
- for(int i = 0; i < mpGroups.length; i++) {
- //遍历每个Group
- mpBufVertices[i].position(0);
- int vertexCount = mpBufVertices[i].limit() / 3;
- int triangleCount = vertexCount / 3;
- //由于我们提交渲染的顶点数据是以三角形列表的形式填充的,不牵扯到索引值
- //因此,每3个顶点就组成一个三角形
- for(int idxTriangle = 0; idxTriangle < triangleCount; idxTriangle++) {
- //遍历每个三角形
- //填充三角形数据,顶点v0, v1, v2
- IBufferFactory.read(mpBufVertices[i], v0);
- IBufferFactory.read(mpBufVertices[i], v1);
- IBufferFactory.read(mpBufVertices[i], v2);
- //进行射线和三角行的碰撞检测
- if(ray.intersectTriangle(v0, v1, v2, location)) {
- //如果发生了相交
- if(!bFound) {
- //如果是初次检测到,需要存储射线原点与三角形交点的距离值
- bFound = true;
- closeDis = location.w;
- trianglePosOut[0].set(v0);
- trianglePosOut[1].set(v1);
- trianglePosOut[2].set(v2);
- } else {
- //如果之前已经检测到相交事件,则需要把新相交点与之前的相交数据相比较
- //最终保留离射线原点更近的
- if(closeDis > location.w) {
- closeDis = location.w;
- trianglePosOut[0].set(v0);
- trianglePosOut[1].set(v1);
- trianglePosOut[2].set(v2);
- }
- }
- }
- }
- //重置Buffer
- mpBufVertices[i].position(0);
- }
- return bFound;
- }
- //-------使用系统函数进行变换
- //gl.glRotatef(mfAngleX, 1, 0, 0);//绕X轴旋转
- //gl.glRotatef(mfAngleY, 0, 1, 0);//绕Y轴旋转
- //-------托管方式进行变换
- Matrix4f matRotX = new Matrix4f();
- Matrix4f matRotY = new Matrix4f();
- matRotX.setIdentity();
- matRotY.setIdentity();
- matRotX.rotX((float)(mfAngleX * Math.PI / 180));
- matRotY.rotY((float)(mfAngleY * Math.PI / 180));
- AppConfig.gMatModel.set(matRotX); AppConfig.gMatModel.mul(matRotY);
- gl.glMultMatrixf(AppConfig.gMatModel.asFloatBuffer());
- /**
- * 变换射线,将结果存储到out中
- * @param matrix - 变换矩阵
- * @param out - 变换后的射线
- */
- public void transform(Matrix4f matrix, Ray out) {
- Vector3f v0 = Vector3f.TEMP;
- Vector3f v1 = Vector3f.TEMP1;
- v0.set(mvOrigin);
- v1.set(mvOrigin);
- v1.add(mvDirection);
- matrix.transform(v0, v0);
- matrix.transform(v1, v1);
- out.mvOrigin.set(v0);
- v1.sub(v0);
- v1.normalize();
- out.mvDirection.set(v1);
- }

- /**
- * 检测射线是否与包围球相交
- *
- * @param center
- * 圆心
- * @param radius
- * 半径
- * @return 如果相交返回true
- */
- public boolean intersectSphere(Vector3f center, float radius) {
- Vector3f diff = tmp0;
- diff.sub(mvOrigin, center);
- float r2 = radius * radius;
- float a = diff.dot(diff) - r2;
- if (a <= 0.0f) {
- //在包围球内
- return true;
- }
- float b = mvDirection.dot(diff);
- if (b >= 0.0f) {
- return false;
- }
- return b * b >= a;
- }
- /**
- * 更新拾取事件
- */
- private void updatePick() {
- if(!AppConfig.gbNeedPick) {
- return;
- }
- AppConfig.gbNeedPick = false;
- //更新最新的拾取射线
- PickFactory.update(AppConfig.gScreenX, AppConfig.gScreenY);
- //获得最新的拾取射线
- Ray ray = PickFactory.getPickRay();
- //首先把模型的绑定球通过模型矩阵,由模型局部空间变换到世界空间
- AppConfig.gMatModel.transform(mModel.getSphereCenter(), transformedSphereCenter);
- //首先检测拾取射线是否与模型绑定球发生相交
- //这个检测很快,可以快速排除不必要的精确相交检测
- if(ray.intersectSphere(transformedSphereCenter, mModel.getSphereRadius())) {
- //如果射线与绑定球发生相交,那么就需要进行精确的三角面级别的相交检测
- //由于我们的模型渲染数据,均是在模型局部坐标系中
- //而拾取射线是在世界坐标系中
- //因此需要把射线转换到模型坐标系中
- //这里首先计算模型矩阵的逆矩阵
- matInvertModel.set(AppConfig.gMatModel);
- matInvertModel.invert();
- //把射线变换到模型坐标系中,把结果存储到transformedRay中
- ray.transform(matInvertModel, transformedRay);
- //将变换后的射线与模型做精确相交检测
- if(mModel.intersect(transformedRay, mpTriangle)) {
- //如果找到了相交的最近的三角形
- AppConfig.gbTrianglePicked = true;
- //填充数据到被选取三角形的渲染缓存中
- mBufPickedTriangle.position(0);
- for(int i = 0; i < 3; i++) {
- IBufferFactory.fillBuffer(mBufPickedTriangle, mpTriangle[i]);
- }
- mBufPickedTriangle.position(0);
- }
- } else {
- AppConfig.gbTrianglePicked = false;
- }
- }
- /**
- * 渲染选中的三角形
- * @param gl
- */
- private void drawPickedTriangle(GL10 gl) {
- if(!AppConfig.gbTrianglePicked) {
- return;
- }
- //由于返回的拾取三角形数据是出于模型坐标系中
- //因此需要经过模型变换,将它们变换到世界坐标系中进行渲染
- //设置模型变换矩阵
- gl.glMultMatrixf(AppConfig.gMatModel.asFloatBuffer());
- //设置三角形颜色,alpha为0.7
- gl.glColor4f(1.0f, 0.0f, 0.0f, 0.7f);
- //开启Blend混合模式
- gl.glEnable(GL10.GL_BLEND);
- gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
- //禁用无关属性,仅仅使用纯色填充
- gl.glDisable(GL10.GL_DEPTH_TEST);
- gl.glDisable(GL10.GL_TEXTURE_2D);
- //开始绑定渲染顶点数据
- gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
- gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mBufPickedTriangle);
- //提交渲染
- gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);
- //重置相关属性
- gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
- gl.glEnable(GL10.GL_DEPTH_TEST);
- gl.glDisable(GL10.GL_BLEND);
- }
IOS 游戏学习笔记一
对游戏和3D一直笔记感兴趣,希望有一天能够开发自己的一款风靡世界的游戏,android和ios平台的出现,有可能把这个希望变成现实,不过在开发出一款真正的游戏之前,得知道怎么编游戏。
找了很多中文资料,都是一些很简单的介绍,后来看到一本英文的ios游戏编程,才了解游戏是这样编写的,为了记录一下心的,准备写一些这方面的教程,也算是给喜欢编游戏的人做个教程。
游戏有很多的引擎,对于初学者,门槛太高,还是先简单的开始,理解了原理,再了解引擎也不迟,有能力自己开发引擎也可。
就我所知道的一些3D opengl es引擎:
android: mini3d andengine libgdx等等,mini3d够简单,可以看看
ios:cocos2d-x
kinect 技术将再几年后改变游戏模式
看到kinetc技术,了解了一些,我觉得对于游戏开发绝对是一个划时代的改变。
这个是一个完全不同的操作模式,完全不同的体验,
再结合各种手机,平板,以及各操作系统平台,会产生许多创新的技术。
可以设想:
1 有一款游戏,可以在电视上玩,通过kinect进行控制,也可以通过iphone ,android
手机进行远程操作,可以运行在mac os 或windows 。
最理想的状态,有硬件开发商开发出独立的可以通过无线连接的kinect ,
所有的平台,mac os ,ios ,android ,windows ,windows phone 等都可以
通过无线调用kinect识别出来的数据,通过在本地,或无线传输到大屏幕,玩各种游戏。
现有的游戏只要增加kinect识别做相应处理,就可以解决游戏不足问题。
2 目前可以做的也有很多创新,娱乐,教育,学习都很很多空白领域等待开发。
——后续
前几天参加csdn的全球软件营销大会,看到一个很酷的设备,google开发的,一个类似中枢的硬件和,通过这个东西,可以无线或蓝牙进行NFC(近距离连接)传输,csdn蒋涛讲了一个玩具和语音结合的互动例子,以后的玩具有更多的智能,互动。
Soft is eating world !
软件正在蚕食着世界,大部分的东西都会软件化,或者软硬结合。
书本的电子化趋势也越来越明显,音乐,电影都数字化,
交互的技术发展,越来越多的创新会出现。
我设想的场景,也行过不了几年就会有:
1 家里有一台设备,移动的设备,家用电器都可以连接在一起,手机的屏幕可以无线传输到电视的大屏幕上。移动的设备上的游戏可以在电视上玩,借助类似kinect技术,完全解放出来,可以玩游戏的同时健身。
2 3D虚拟技术的成熟,通过佩戴3D眼镜,通过无线连接,完全可以没有显示设备,自己在3D眼镜显示,或显示在电视大屏幕上,结合kinect技术,就像漫游在真正的3D世界中,可以约朋友一起在虚拟的3D世界中一起跑步,玩游戏。现在的CS游戏,如果穿一身有反馈的衣服,AK手枪等设备能够反馈信息到系统中,那么这个游戏一定会很吸引人 。也许将来某一天,有一种体验馆,可以利用这种最先进的3D体感技术,实现虚拟3D时间的无缝融合。
关于大型多人交互在线系统初步方案
有朋友咨询开发多人在线聊天系统,比较了一些受访和开源的系统,归纳如下:
1 服务端选择smrtfoxserver 2.x :服务端开发可以选择的java 或python ,python可以快速的开发原型demo ,java也是比较好的选择,有很多的开源代码可用。客户端支持android ,actionscript ,unity 3d ,silverlight 等等,基本说对于移动开发可以包含。
有现成的成功案例,大公司也采用,不用担心性能问题,唯一缺点,费用太贵,免费可用100个用户。
2 服务端采用openfire 开源服务器:服务端采用java开发,内部使用mina 实现网络接口,mina也是和netty xsocket类似的无阻塞网络协议实现。客户端目前只能用android ,使用asmack库。采用xmpp协议实现消息流 。
3 如果不考虑手机端,可以采用node.js +websocket 实现,这个也是比较好。
4 可以考虑采用tornado python web服务器,这个也是无阻塞,支持1K以上用户连接。
5 建议采用amazon的ec服务器,以后扩展方便 ,前段nginx + tornado ,采用python 开发,客户端技术使用html5 +本地调用,平台:web+android +ios+wp7 ,使用rest接口进行数据交换 ,可用json格式,数据库:amazon的mysql 。
6 采用google gae + cloud sql ,优点:不必考虑服务扩展,google帮你做好了。
缺点: 限定了开发语言和环境。
本人没用过,接下来准备使用该5方案做一个demo :
目标:搭建一个以图片交流的平台,用户可用方便的手写后和其他用户交流,能同事容纳100K用户
周期: 1年 业余开发