zoukankan      html  css  js  c++  java
  • 【C++】 网络编程 01

    趁着计算机网络这门课布置了课程设计,学习下网络编程。

    系统:Ubuntu 14.01...

    1. 关于Socket(套接字)

    1.1

    套接字是存在于运输层和应用层间的抽象层,通过它来区分不同应用程序进程间的网络通信和连接。

    其主要包含3个参数:通信的目的IP地址、使用的传输层协议(TCP或UDP)和使用的端口号。

    1.2

    套接字的通信流程:

    1.3

    socket()函数:

    int socket(int domain, int type, int protocol);

    其中:

    • domain为创建的套接字指定协议集。
      • AF_INET 表示IPv4网络协议
      • AF_INET6 表示IPv6网络协议
      • AF_UNIX 表示本地套接字
    • type 如下:
      • SOCK_STREAM (可靠的面向流服务或流套接字)
      • SOCK_DGRAM (数据报文服务或者数据报文套接字)
      • SOCK_SEQPACKET (可靠的连续数据包服务)
      • SOCK_RAW (在网络层之上的原始协议)
    • protocol 指定实际使用的传输协议。 如果该项为“0”的话,即根据选定的domain和type选择使用缺省协议。(目前也只遇到了0)

    connection()函数:

    int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
    • socket即socket()函数返回值
    • myaddr 表示指向sockaddr结构(用于表示所分配地址)的指针
    • addrlen表示sockaddr结构的长度

    当返回值为-1,表示出错;返回0表示连接成功。

    先编写客户端程序client.cpp,创建一个套接字:

    #include<iostream>
    #include<sys/socket.h>
    using namespace std;
    
    int main()
    {
        int socket_desc;
        socket_desc = socket(AF_INET , SOCK_STREAM , 0);
         
        if (socket_desc == -1)
        {
            cout<<("Could not create socket");
        }
         
        return 0;
    }

    1.4

    接下来将这个套接字连接到Server上,需要ip地址和端口号

    使用sockaddr_in对需要连接到的服务器进行设定,sockaddr_in和sockaddr结构:

    // IPv4 AF_INET sockets:
    struct sockaddr_in {
        short            sin_family;   // e.g. AF_INET, AF_INET6
        unsigned short   sin_port;     // e.g. htons(3490)
        struct in_addr   sin_addr;     // see struct in_addr, below
        char             sin_zero[8];  // zero this if you want to
    };
     
    struct in_addr {
        unsigned long s_addr;          // load with inet_pton()
    };
     
    struct sockaddr {
        unsigned short    sa_family;    // address family, AF_xxx
        char              sa_data[14];  // 14 bytes of protocol address
    };

    尝试连接到baidu.com的服务器,ip:14.215.177.37,ip地址是256进制的4字节数据,如14.215.177.37(baidu.com),用inet_addr函数将它转化成长整数类型:

    server.sin_addr.s_addr = inet_addr("14.215.177.37");  

    向上述代码添加sockaddr_in结构体对象server:

    #include<iostream>
    #include<sys/socket.h>
    #include<arpa/inet.h>
    
    using namespace std;
    
    int main()
    {
        int socket_desc;
        struct sockaddr_in server;  
    //create socket socket_desc = socket(AF_INET, SOCK_STREAM, 0); if(socket_desc == -1) { cout<<"Could not creat socket"<<endl; } server.sin_addr.s_addr = inet_addr("14.215.177.37"); server.sin_family = AF_INET; server.sin_port = htons(80); //connect to remote server if(connect(socket_desc, (struct sockaddr*)&server, sizeof(server))<0) { cout<<("connect error")<<endl; return 1; } cout<<("Connected")<<endl; return 0; }

    如果无误,运行后控制台会显示"Connected",连接成功

    tips:Connections are present only in tcp sockets

    1.5

    用send()函数实现通过Socket发送数据

    send()函数:

    int send(int socket, const void * buff, int length, int flags);

    recv()函数:

    int recv(int socket, void *buff, int length, int flags);
    • *buff是指向待传输数据buffer的指针
    • length是待传输数据的长度
    • flags标志调用方式,一般置0(?)

    向baidu的服务器发送请求并获取回复:

    #include<iostream>
    #include<string.h>
    #include<sys/socket.h>
    #include<arpa/inet.h>
    
    using namespace std;
    
    int main()
    {
        int socket_desc;
        struct sockaddr_in server;
        char *msg, server_reply[2000];
    
        //create socket
        socket_desc = socket(AF_INET, SOCK_STREAM, 0);
        if(socket_desc == -1)
        {
            cout<<"Could not creat socket"<<endl;
        }
    
        server.sin_addr.s_addr = inet_addr("64.233.187.105");
        server.sin_family = AF_INET;
        server.sin_port = htons(80);
    
        //connect to remote server
        if(connect(socket_desc, (struct sockaddr*)&server, sizeof(server))<0)
        {
            cout<<("connect error")<<endl;
            return 1;
        }
    
        cout<<("Connected")<<endl;
    
        //send data
        msg = "GET / HTTP/1.1
    
    ";     //    HTTP Request
        if(send(socket_desc, msg, strlen(msg), 0)<0)
        {
            cout<<"Send failed"<<endl;
            return 1;
        }
        cout<<"Data send
    "<<endl;
    
        //Recieve a reply from the server
        if(recv(socket_desc, server_reply, 2000, 0)<0)
        {
            cout<<"Recv failed"<<endl;
        }
        cout<<"Reply revieved
    "<<endl;
        cout<<server_reply<<endl;
    
        return 0;
    }
    其中 "GET / HTTP/1.1" 是HTTP请求...具体什么意思暂时并不明白,但可以验证发送成功
    返回如下信息:
    Connected
    Data send
    
    Reply revieved
    
    HTTP/1.1 302 Moved Temporarily
    Date: Fri, 10 Jun 2016 21:01:45 GMT
    Content-Type: text/html
    Content-Length: 215
    Connection: Keep-Alive
    Location: http://www.baidu.com/search/error.html
    Server: BWS/1.1
    X-UA-Compatible: IE=Edge,chrome=1
    BDPAGETYPE: 3
    Set-Cookie: BDSVRTM=0; path=/

    1.6
    最后关闭socket,用unistd.h中的close()函数:
    close(socket_desc);

    1.7
    以上完成了三个基本操作:
    1. 创建套接字
    2. 建立与服务器的连接
    3. 发送和接收信息

    【Over】

  • 相关阅读:
    Swift-'as?','as'用法
    Swift-'!','?'用法
    Swift-Debug下打印函数名和行数
    Swift-Swift中的全局变量和函数的创建
    Swift/Objective-C-Swift与Objective-C混用教程
    iOS-代码修改Info.plist文件
    hexo干货系列:(八)hexo文章自动隐藏侧边栏
    hexo干货系列:(七)hexo安装统计插件
    hexo干货系列:(六)hexo提交搜索引擎(百度+谷歌)
    hexo干货系列:(五)hexo添加站内搜索
  • 原文地址:https://www.cnblogs.com/liez/p/5574652.html
Copyright © 2011-2022 走看看