Cocos网络篇[3.2](3) ——Socket连接(1)

2015-03-05 22:24:13

标签:network http socket cocos

【唠叨】

在客户端游戏开发中,使用HTTP进行网络通信的比较少,一般使用的都是Socket进行通信。而HTTP一般用于网页或者网页游戏。

使用第三方Socket通信库:ODSocket

【参考】

http://blog.csdn.net/sight_/article/details/8138802 (Socket详解)

http://blog.csdn.net/hguisu/article/details/7444092 (Socket编程原理)

【源码下载】

ODSocket库源码https://github.com/shahdza/Cocos_LearningTest/tree/master/ODSocket

本节Demo源码https://github.com/shahdza/Cocos_LearningTest/tree/master/ODSocket_Demo1


【Socket简介】

1、套接字(socket)概念

套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。

套接字: { IP地址 : 端口号 }

应用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要通过同一个TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了套接字(Socket)接口。应用层可以和传输层通过Socket接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。

2、套接字类型  

TCP/IP的socket提供下列三种类型套接字。

2.1、流式套接字(SOCK_STREAM)

提供了一个面向连接(TCP)、可靠的数据传输服务,数据无差错、无重复地发送,且按发送顺序接收。内设流量控制,避免数据流超限;数据被看作是字节流,无长度限制。文件传送协议(FTP)即使用流式套接字。

2.2、数据报式套接字(SOCK_DGRAM)

提供了一个无连接服务(UDP)。数据包以独立包形式被发送,不提供无错保证,数据可能丢失或重复,并且接收顺序混乱。网络文件系统(NFS)使用数据报式套接字。

2.3、原始式套接字(SOCK_RAW) 

该接口允许对较低层协议,如IP、ICMP直接访问。常用于检验新的协议实现或访问现有服务中配置的新设备。

3、建立socket连接

建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket ,另一个运行于服务器端,称为ServerSocket 。

套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。

(a)服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。

(b)客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。

(c)连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。

4、典型套接字调用过程举例

TCP/IP协议的应用一般采用客户/服务器模式,因此在实际应用中,必须有客户和服务器两个进程,并且首先启动服务器,其系统调用时序图如下。

面向连接的协议(TCP)的套接字系统调用如下:

> 服务器必须首先启动,直到它执行完accept()调用,进入等待状态后,方能接收客户请求。

> 假如客户在此前启动,则connect()将返回出错代码,连接不成功。

无连接的协议(UDP)的套接字调用如下:

> 无连接服务器也必须先启动,否则客户请求传不到服务进程。

> 无连接客户不调用connect()。因此在数据发送之前,客户与服务器之间尚未建立完全相关,但各自通过socket()和bind()建立了半相关。

> 发送数据时,发送方除指定本地套接字号外,还需指定接收方套接字号,从而在数据收发过程中动态地建立了全相关。


【Socket连接】

使用的是面向连接的TCP套接字系统调用API。

0、将ODSocket源码放在Classes目录下

1、客户端

使用ODSocket的API实现与服务端的网络连接。

> 创建ODSocket:ODSocket socket;

> 初始化:Init() 、 Create();

> 设置需要连接的服务器的 IP地址和端口号:ip 、 port;

> 连接服务器:Connet(ip, port);

> 发送数据:Send(string, lenght);

> 接收数据:Recv(string, lenght, 0);

> 关闭连接:Close();

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//
// 引入头文件
#include "ODSocket/ODSocket.h"
 
// Socker连接
void HelloWorld::connectServer()
{
    // 初始化
    // ODSocket socket;
    socket.Init();
    socket.Create(AF_INET, SOCK_STREAM, 0);
     
    // 设置服务器的IP地址,端口号
    // 并连接服务器 Connect
    const char* ip = "127.0.0.1";
    int port = 12345;
    bool result = socket.Connect(ip, port);
     
    // 发送数据 Send
    socket.Send("login", 5);
     
    if (result) {
        CCLOG("connect to server success!");
        // 开启新线程,在子线程中,接收数据
        std::thread recvThread = std::thread(&HelloWorld::receiveData, this);
        recvThread.detach(); // 从主线程分离
    }
    else {
        CCLOG("can not connect to server");
        return;
    }
}
 
// 接收数据
void HelloWorld::receiveData()
{
    // 因为是强联网
    // 所以可以一直检测服务端是否有数据传来
    while (true) {
        // 接收数据 Recv
        char data[512] = "";
        int result = socket.Recv(data, 512, 0);
        printf("%d", result);
        // 与服务器的连接断开了
        if (result <= 0) break;
         
        CCLOG("%s", data);
    }
    // 关闭连接
    socket.Close();
}
//

2、服务端

使用Eclipse开发环境,Java语言,服务端使用的是 ServerSocket 来监听端口。

2.1、Server类

用于创建ServerSocket,监听端口,等待客户连接。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//
public class Server {
 
    public static void main(String[] args) throws IOException {
         
        // 创建ServerSocket,监听端口号:12345
        ServerSocket ss = new ServerSocket(12345);
        // 创建用于管理客户端的收发数据的子线程类
        ClientThread clientThread = new ClientThread();
        clientThread.start();
         
        System.out.println("服务器开启啦");
 
        // 监听端口号:12345
        // 等待客户连接 accept()
        while (true) {
            // 开始接收客户端的连接
            Socket socket = ss.accept();
            System.out.println("有新客户连接~");
            clientThread.addClient(socket);
        }
    }
}
//

2.2、ClientThread类

用于管理、处理客户端的收发数据请求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
//
// 继承Thread线程类
public class ClientThread extends Thread {
    // 客户端连接的socket列表
    private ArrayList<Socket> clients = new ArrayList<Socket>();
 
    // 添加客户
    public void addClient(Socket socket) {
        clients.add(socket);
    }
    // 删除客户
    public void removeClient(Socket socket) {
        clients.remove(socket);
    }
    // 向客户发送数据
    public void sendMessage(Socket socket, String data) throws IOException {
        // 给玩家发送数据
        OutputStream os = socket.getOutputStream();
        os.write(data.getBytes("UTF-8"));
    }
 
    @Override
    public void run() {
        while (true) {
            try {
                for (Socket socket : clients) {
                    // 获取客户端发来的数据
                    InputStream is = socket.getInputStream();
                    int len = is.available() + 1;
                    byte[] buff = new byte[len];
                    int flag = is.read(buff);
 
                    // read()返回-1,说明客户端的socket已断开
                    if (flag == -1) {
                        System.out.println("有客户断开连接~");
                        this.removeClient(socket);
                        break;
                    }
 
                    // 输出接收到的数据
                    String read = new String(buff);
                    System.out.println("收到数据:" + read);
 
                    // 给玩家发送数据
                    String data = "恭喜你,连接成功啦~~";
                    sendMessage(socket, data);
                }
                sleep(10);
            catch (IOException e) {
                e.printStackTrace();
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
//

3、运行服务器

在Eclipse开发工具中,运行服务器程序。

4、运行客户端

然后运行客户端试试。

客户端输出:

服务端输出:

5、关闭客户端程序

服务端输出:

转 Cocos网络篇[3.2](3) ——Socket连接(1)的更多相关文章

  1. Python 网络编程 C/S建立Socket连接

    分为客户端和服务端 服务端 server.py 客户端 1 #coding=utf-8 2 import socket 3 4 client = socket.socket() #生成socket连接 ...

  2. iOS开发网络篇—Socket编程

    一.网络各个协议:TCP/IP.SOCKET.HTTP等 网络七层由下往上分别为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层. 其中物理层.数据链路层和网络层通常被称作媒体层,是网络工程 ...

  3. iOS开发网络篇—文件的上传

    iOS开发网络篇—文件的上传 说明:文件上传使用的时POST请求,通常把要上传的数据保存在请求体中.本文介绍如何不借助第三方框架实现iOS开发中得文件上传. 由于过程较为复杂,因此本文只贴出部分关键代 ...

  4. Android应用开发基础篇(12)-----Socket通信

    链接地址:http://www.cnblogs.com/lknlfy/archive/2012/03/03/2378669.html 一.概述 网络通信无论在手机还是其他设备上都应用得非常广泛,因此掌 ...

  5. Python 经典面试题汇总之网络篇

    网络篇 1.简述 OSI 七层协议 物理层:定义物理设备标准,如网线的接口类型.光纤的接口类型.各种传输介质. 数据链路层:定义如何传输格式化数据,以及如何访问物理介质. 网络层:定义逻辑网络地址. ...

  6. 【转】一文掌握 Linux 性能分析之网络篇(续)

    [转]一文掌握 Linux 性能分析之网络篇(续) 在上篇网络篇中,我们已经介绍了几个 Linux 网络方向的性能分析工具,本文再补充几个.总结下来,余下的工具包括但不限于以下几个: sar:统计信息 ...

  7. 【转】一文掌握 Linux 性能分析之网络篇

    [转]一文掌握 Linux 性能分析之网络篇 比较宽泛地讲,网络方向的性能分析既包括主机测的网络配置查看.监控,又包括网络链路上的包转发时延.吞吐量.带宽等指标分析.包括但不限于以下分析工具: pin ...

  8. 一文掌握 Linux 性能分析之网络篇(续)

    本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. 这是 Linu ...

  9. 《Linux大棚命令百篇下》网络篇的总结

    本文是<Linux大棚命令百篇下>网络篇的总结 ping -c 指定数量,在windows下会自动停止,linux下会一直ping下去 -q 简短报告 -s 指定每次ping的数据包大小, ...

随机推荐

  1. JS调用Java函数--DWR框架

    (1)dwr与ssh框架整合教程dwr框架介绍. DWR(Direct Web Remoting)是一个用于改善web页面与Java类交互的远程服务器端Ajax开源框架,可以帮助开发人员开发包含AJA ...

  2. Linux中文显示乱码解决

    输入 echo $LANG可以查看当前使用的系统语言 查看是否有中文语言包可以在终端输入 locale命令,如有zh cn 表示已经安装了中文语言 没有则 yum groupinstall chine ...

  3. 【jQuery UI 1.8 The User Interface Library for jQuery】.学习笔记.9.Progressbar控件

    Progressbar控件用来显示任意进程的完成百分比. 默认安装启用 配置选项 控件暴露的事件API progressbar暴露的独一无二的方法 一些现实生活的例子 当前版本中,我们或系统必须明确进 ...

  4. 更改MySQL数据文件目录位置

    运维mysql,某些时候需要将数据文件更改到别的路径.以下介绍将mysql的数据文件从/var/lib/mysql迁移到/home/mysqldata/mysql下. 1.停止mysql $ serv ...

  5. Swoole 遇上 PHP会是怎样的结果呢

    一直想写点Swoole的东西,毕竟它重新定义了php,却一直不知道怎么下手写 Swoole涉及的知识点非常多,互为表里,每次想写都发现根本理不出一个头绪 Swoole是一个php的扩展,它的核心目的就 ...

  6. JavaEE基础(二十三)/递归

    1.File类递归练习(统计该文件夹大小) 需求:1,从键盘接收一个文件夹路径,统计该文件夹大小 2.File类递归练习(删除该文件夹) 需求:2,从键盘接收一个文件夹路径,删除该文件夹 3.File ...

  7. ftp服务的搭建及调用

    首先是搭建 ftp server: 下载:http://archive.apache.org/dist/mina/ftpserver/1.0.6/ 下载到本地, 如下图:

  8. html移动开发app-framework2.0使用心得

    1.页面切换动画结束时卡(禁用动画) 2.搜索或导航标签需要固定(标签选择器动态修改高度) 3.pancel容器默认生成的时候内容不放 通过动态的的$("").empty().ht ...

  9. 过滤器Filter(拦截jsp页面的跳转)案例:

    创建一个 Filter , class类: 其继承于 接口 Filte(接口导包:import javax.servlet.Filter;) 在 web.xml 文件中配置并映射该 Filter. 其 ...

  10. Linux文件描述符与打开文件之间的区别(转载)

    转载请说明出处:http://blog.csdn.net/cywosp/article/details/38965239   1. 概述     在Linux系统中一切皆可以看成是文件,文件又可分为: ...