Cocos2dx网络学习笔记(一)

Cocos2dx网络学习笔记(一)

学习资料

C++ Socket 编程

简单的服务器

直接上代码,再一一解释用到的东西

#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
using namespace std;

#define SOCKET      int
#define ListenPort  9999

int main()
{
    SOCKET st = socket( AF_INET, SOCK_STREAM, 0 );
    if ( st == -1 )
    {
        cout << "create socket failed" << endl;
        return 0;
    }
    struct sockaddr_in my_addr;
    my_addr.sin_family  = AF_INET;
    my_addr.sin_port    = htons( ListenPort );
    my_addr.sin_addr.s_addr = INADDR_ANY;   /* inet_addr("127.0.0.1"); */
    memset( my_addr.sin_zero, 0, 8 );
    int result = ::bind( st, (struct sockaddr *) (&my_addr), sizeof(struct sockaddr) );
    if ( result == -1 )
    {
        cout << "bind socket failed" << endl;
        return 0;
    }
    result = listen( st, 1 );
    if ( result == -1 )
    {
        cout << "listen socket failed" << endl;
        return 0;
    }
    struct sockaddr_in  new_addr;
    socklen_t       sin_size    = sizeof(struct sockaddr_in);
    SOCKET          new_connect = accept( st, (struct sockaddr *) (&new_addr), &sin_size );
    if ( new_connect != -1 )
    {
        char* ip = inet_ntoa( new_addr.sin_addr );
        cout << "new connect from " << ip << " with port:" << new_addr.sin_port << endl;
        char buf[1024];
        while ( true )
        {
            int recv_bytes = ::recv( new_connect, &buf, 1024, 0 );
            if ( recv_bytes == -1 )
            {
                cout << "recv failed" << endl;
                break;
            }
            cout << "receive from client:" << buf << endl;
            string message = buf;
            message = "this is reply for " + message;
            int reply_len   = message.length();
            int send_bytes  = ::send( new_connect, message.c_str(), reply_len, 0 );
            if ( send_bytes == -1 )
            {
                cout << "send failed" << endl;
                break;
            }
        }
    }
    return 0;
}
  1. 首先是头文件:

        #include <sys/types.h> 
        #include <sys/socket.h>
        #include <netinet/in.h>
        #include <arpa/inet.h>

    这几个基本是常用的,其他常用的网络头文件可以看这个 linux网络编程常用头文件, windows下是#include <winsock.h>

  2. int socket(int domain, int type, int protocol);
    创建一个socket,第一个和第三个参数分别是域和协议,一般直接用这个就好,第二个参数是使用哪种协议,SOCK_STREAM是TCP,SOCK_DGRAM是UDP的,返回值为-1表示创建失败

  3. struct sockaddr_in
    这个结构体是为了更方便的处理sockaddr的,添加监听、连接服务器的相关配置都是这个结构体,两者可以强转,原型是

    struct sockaddr_in {
        short int sin_family;           /* 通信类型,跟创建socket的第1个参数一致 */
        unsigned short int sin_port;    /* 端口 */
        struct in_addr sin_addr;        /* Internet 地址 
                                           struct in_addr {
                                             unsigned long s_addr;
                                            };*/
        unsigned char sin_zero[8];      /* 与sockaddr结构的长度相同*/
    };

    因为网络和本机的字节顺序不一样,sin_port需要通过htons(host to network short)转换, ip地址也需要转换,不过可以使用专门的函数inet_addr("ip"),特别的,INADDR_ANY表示本机地址。sin_zero需要用memset或者bzero清零。

  4. int bind(int sockfd, struct sockaddr *my_addr, int addrlen);
    绑定端口,第1个参数是创建的socket;第二个参数可以用sockaddr_in,绑定哪个端口也是这个参数指定;addrlen直接用sizeof(struct sockaddr)。绑定失败(如端口占用等)返回值为-1。
  5. int listen(int sockfd, int backlog);
    socket开始监听,backlog表示最多可接收的连接数,可根据服务器性能设置
  6. int accept(int sockfd, void *addr, int *addrlen);
    开始接听后调用accept会阻塞,直至有一个新连接到来。返回值是新连接的socket,你可以使用这个socket去接受和发送消息。void *addr可以获取新连接的参数,如IP,端口等。后两个参数跟bind类似。注意一点,获取到的参数信息是网络字节顺序,需要转换成本机自己顺序才可正确使用,ntohs(network to host short)和inet_ntoa
  7. int recv(int sockfd, void *buf, int len, unsigned int flags);
    接收sockfd的消息,默认是阻塞式。新消息内容将被存储到buf, len是buf可存储的最大数量,flags可设置为0,返回值是实际接收了多少数据。错误返回-1,断开连接等通常返回0
  8. int send(int sockfd, const void *msg, int len, int flags);
    给sockfd发送消息,阻塞。msg是消息内容,len是需要发送的消息长度,flags可设置为0.返回值是实际发送了多少内容。
  9. 注意事项: std中也有recv和send函数,在recv前面加::可以表明是使用socket的recv。在using namespace std;的情况下要特别注意.
  10. 可以使用终端命令telnet 127.0.0.1 9999测试

简单的客户端

bindlistenaccept都是服务器端用的函数,客户端用的就只需要一个connect

int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
创建socket完成后调用此函数,serv_addr是服务器的地址和端口。错误返回-1

示例代码:

#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
using namespace std;

#define SOCKET      int
#define ListenPort  9999

using namespace std;
int main(int argc, char *argv[]) {
    SOCKET st = socket( AF_INET, SOCK_STREAM, 0 );
    if ( st == -1 )
    {
        cout << "create socket failed" << endl;
        return 0;
    }
    struct sockaddr_in server_addr;
    server_addr.sin_family  = AF_INET;
    server_addr.sin_port    = htons( ListenPort );
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");;
    memset( server_addr.sin_zero, 0, 8 );
    int result = connect(st, (struct sockaddr*)(&server_addr), sizeof(struct sockaddr));
    if (result == -1)
    {
        cout << "connect server failed" << endl;
        return 0;
    }

    string message;
    while (true) {
        cin >> message;
        cout << "send to server:" << message << endl;
        int reply_len   = message.length();
        int send_bytes  = ::send( st, message.c_str(), reply_len, 0 );
        if ( send_bytes == -1 )
        {
            cout << "send failed" << endl;
            break;
        }

        char buf[1024];
        int recv_bytes = ::recv( st, &buf, 1024, 0 );
        if ( recv_bytes == -1 )
        {
            cout << "recv failed" << endl;
            break;
        }
        cout << "receive from server:" << buf << endl;
    }
    return 0;
}

运行结果

服务器 + telnet
服务器

telnet

服务器 + 客户端
服务器

客户端

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lyzz0612

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值