加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

Cocos2d-x开发网络游戏(一)

(2012-12-25 09:23:10)
标签:

cocos2d

网络

socketcc

服务器

it

分类: Cocos2D

欢迎加入开发群:285275050 交流
游戏如果脱离了网络,那么它的可玩性将会大大降低,其生命周期也相对较短,小鸟与水果就把它当成神话好了。本人也是最近接触网络游戏的开发,写这个主要是记录一下自己的学习过程,同时也为以后的开发做个热身运动,至于写到哪里写到什么程度,我也没有确切打算,当然最好是能对立出一个小的游戏工程。

从网上查资料了解到网络游戏的网络连接部分主要有tcp连接和udp连接,由于对游戏的要求不同选择哪种,要根据实际情况,通常局域网对战类游戏为udp,因为局域网内数据传输相对稳定。在这里服务器端选用的开发语言为java,而客户端选用的开发语言为cocos2d-x的开发语言为c++。对于socket编程,cocos2dx没有一如第三方的开发库,这样要实现跨平台的socket我们就只能选用BSD SocketBSD Socket不需要引入第三方开发库,各个平台基本都支持。不过有些遗憾的BSD Socket不符合面向对象的编程原则(为c语言),不过还好,我们可以自己去集成第三方开发库。在这里我选用了第三方的开发库socketccpthreadcc,他们是对bsd socket的一个c++封装,我已经成功在androidios下编译。如果对如何在这两个平台引入和使用这两个库,可以看我前面的文章,在那里我有详细的介绍。

好了,今天我们险通过tcp连接,并通过tcp来传送数据来把客户端输入的用户名密码提交给服务器。Ok,开始吧!

 

首先看客户端界面

http://s12/mw690/6084f588t7b5d1e4468bb&690

 

 

 

界面代码:

void LoginScene::loadUI(){

    CCSize editBoxSize = CCSizeMake(200, 60);

    _pEditName = CCEditBox::create(editBoxSize, CCScale9Sprite::create("green_edit.png"));

    _pEditName->setPosition(ccp(512, 680));

    _pEditName->setFontColor(ccRED);

    _pEditName->setPlaceHolder("Name:");

    _pEditName->setMaxLength(8);

    _pEditName->setReturnType(kKeyboardReturnTypeDefault);

    _pEditName->setDelegate(this);

    addChild(_pEditName);

   

    _pEditPwd = CCEditBox::create(editBoxSize, CCScale9Sprite::create("green_edit.png"));

    _pEditPwd->setPosition(ccp(512, 600));

    _pEditPwd->setFontColor(ccRED);

    _pEditPwd->setPlaceHolder("Password:");

    _pEditPwd->setMaxLength(8);

    _pEditPwd->setReturnType(kKeyboardReturnTypeDone);

    _pEditPwd->setDelegate(this);

    addChild(_pEditPwd);

}

 

当出发提交时执行:

void SocketClient::login(const char * userName,const char * userPwd){

    if (userName==NULL||userPwd==NULL) {

        return;

    }

    if (strlen(userName)>0&&strlen(userPwd)>0) {

        _tcpSocket->SendASCII(userName);

        _tcpSocket->SendASCII(userPwd);

    }

}

 

 

服务器端:

main中调用start方法,start方法当有客户接入时,开始一个客户端线程用于接收客户端发来的数据。

 

public void start(){

             ServerSocket ss=null;

             try {

                 ss=new ServerSocket(9999);

             } catch (Exception e) {

                 e.printStackTrace();

             }

            

             while(true){

                 Socket clientSocket=null;

                 try {

                     clientSocket=ss.accept();

                     System.out.println("a client connected!");

                     DataInputStream dis=new DataInputStream(clientSocket.getInputStream());

                    

                     byte bytesRead[]=new byte[20];

                     dis.read(bytesRead);

 

                     String strValue=new String(bytesRead);

                     System.out.println("receiveValue="+strValue);

                    

                     new Thread(new TCPClientThread(clientSocket)).start();

 

                 } catch (IOException e) {

                     // TODO Auto-generated catch block

                     e.printStackTrace();

                 }

                

             }

 

内部线程类:

private class TCPClientThread implements Runnable {

             Socket cSocket=null;

            

             public TCPClientThread(Socket cliSocket) {

                 super();

                 this.cSocket = cliSocket;

             }

 

             public void run() {

                 while(cSocket!=null){

                     DataInputStream dis=null;

                     try {

                         dis=new DataInputStream(cSocket.getInputStream());

                         byte buf[]=new byte[60];

                         dis.read(buf);

                         System.out.println(new String(buf));

                     } catch (IOException e) {

                         // TODO Auto-generated catch block

                         e.printStackTrace();

                     }

                    

                 }

             }

 

         }

当收到数据时会将收到的数据打印。

运行服务器并提交数据:

http://s5/mw690/6084f588t7b5d1e5ab434&690

可以看到服务器接收到了我闷得数据,

这时是否会感觉奇怪,我明明发了两次,

void SocketClient::login(const char * userName,const char * userPwd){

    if (userName==NULL||userPwd==NULL) {

        return;

    }

    if (strlen(userName)>0&&strlen(userPwd)>0) {

        _tcpSocket->SendASCII(userName);

        _tcpSocket->SendASCII(userPwd);

    }

}

而且服务器也是没接收一次就输出一行,为什么服务器只接收了一次。

其实这是不可避免的,服务器接收时是以网络字节流来接收的,这是就不可避免的产生分包和粘包等问题,为了能正确接收数据我们就得自己去定义消息,并按消息定义原则自己对收到的数据重新组装。

今天先介绍到这。

 

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有