• Winsock编程基础2(Winsock编程流程)


    1、套接字的创建和关闭
     
    //创建套接字
    SOCKET socket(
        int af,        //指定套接字使用的地址格式,Winsock只支持AF_INET
        int type,    //套接字类型
        int protocol//配合type使用,使用的协议
    );
    //---type
    /*
    * SOCKET_STREAM 流套接字,TCP
    * SOCKET_DGRAM    数据报套接字UDP
    * SOCK_RAW        原始套接字
    */
    //type使用上面两种时,protocol可直接赋0
    //创建失败返回 INVALID_SOCKET(-1),可通过WSAGetLastError获得错误代码
    //也可以使用WSASocket创建套接字,现在先不讨论
        
    //关闭套接字
    int closesocket(SOCKET s);    //s为要关闭套接字句柄
     2、绑定IP和端口号
    int bind(
        SOCKE s,    //套接字句柄
        const struct socketaddr* name,    //要关联的本地地址
        int nameLen    //地址长度
    );
    //bind作用在没有建立连接的套接字上
    
    //绑定示例
    //填充sockaddr_in结构
    sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(4567);    //为0时主机也会自动配置
    addr.sin_addr.S_un.S_addr = INADDR_ANY;    //自动使用当前主机配置
    //绑定这个套接字到一个本地地址
    if(bind(sListen, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR)//sListen是一个套接字
    {
        cout << "Failed bind()" << endl;
        return 0;
    }
     3、设置套接字进入监听状态
    int listen(
        SOCKET s,    //套接字句柄
        int backlog    //监听队列中允许保持的尚未处理的最大连接数,队满客户端会收到WSAECONNREFUSED
    );
     4、接受连接请求
    SOCKET accept(        //返回实际连接的套接字,与s有相同属性
        SOCKET s,
        struct sockaddr* addr,    //指向sockassr_in结构指针,用于获得对方信息
        int *addrLen    //指向地址长度指针
    );
     5、客户端创建套接字后的请求与服务器连接
    int connect(
        SOCKET s,    //客户端套接字
        const struct sockaddr FAR *name,    //包含了要连接的服务器的地址信息
        int nameLen
    );
     6、收发数据
    int send(
        SOCKET s,    //
        const char FAR *buf,    //要发送的数据缓冲区地址
        int Len,    //缓冲区长度
        int flags    //调用方式,常设0
    );
    int recv(SOCKET s, char FAR *buf, int len, int flags)
    简单实例
    //服务器端
    #include <iostream>
    #include <stdio.h>
    
    #include "InitSock.h"
    
    using namespace std;
    int main(void)
    {
        CInitSock initSock;
        SOCKET sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (sListen == INVALID_SOCKET)
        {
            cout << "Failed socke()" << endl;
            return 0;
        }
        //填充sockaddr_in结构
        sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(4567);    
        addr.sin_addr.S_un.S_addr = INADDR_ANY;    
        //绑定这个套接字到一个本地地址
        if (bind(sListen, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR)
        {
            cout << "Failed bind()" << endl;
            return 0;
        }
    
        //进入监听模式
        if (listen(sListen, 2) == SOCKET_ERROR)
        {
            cout << "Failed listen()" << endl;
            return 0;
        }
    
        //循环接受客户端连接请求
        sockaddr_in remoteAddr;    //远程客户端信息
        int nAddrLen = sizeof(remoteAddr);
        SOCKET sClient;
        char szText[] = "TCP Sever Demo!\r\n";
        while (true)
        {//接受新连接
            sClient = accept(sListen, (SOCKADDR *)&remoteAddr, &nAddrLen);
            if (sClient == INVALID_SOCKET)
            {
                cout << "Failed accept()" << endl;
                continue;
            }
    
            cout << "接受一个连接: " << inet_ntoa(remoteAddr.sin_addr) <<endl;;    //inet_ntoa()实际已过时,只能处理IPv4
            //向客户端发送数据
            send(sClient, szText, strlen(szText), 0);
            //关闭通客户端的连接
            closesocket(sClient);
        }    
        //关闭监听套接字
        closesocket(sListen);
        return 0;
    }
     客户端
    #include <iostream>
    #include <stdio.h>
    
    #include "InitSock.h"
    
    using namespace std;
    int main(void)
    {
        CInitSock initSock;
        //创建套接字
        SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (s == INVALID_SOCKET)
        {
            cout << "Failed socke()" << endl;
            return 0;
        }
        //也可以在这里调用binding函数绑定一个本地连接
        //否则系统会自动安装
        //...
        //填写远程地址信息
        sockaddr_in servAddr;
        servAddr.sin_family = AF_INET;
        servAddr.sin_port = htons(4567);
        servAddr.sin_addr.S_un.S_addr = INADDR_ANY;
    
        //注意这里要填写远程服务器的TCP地址
        //本地回环127.0.0.1
        servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
        if (connect(s, (sockaddr*)&servAddr, sizeof(servAddr)) == -1)
        {
            cout << "Failed connect()" << endl;
            return 0;
        }
    
        //接受数据
        char buff[256];
        int nRecv = recv(s, buff, 256, 0);
        if (nRecv > 0)
        {
            buff[nRecv] = '\0';
            cout << buff << endl;
        }
        //关闭套接字
        closesocket(s);
        getchar();
        return 0;
    }
     
     
     
     
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    Bitnami Redmine安装和插件配置
    DataTable转换成List<T>
    学习Javascript闭包(Closure)
    单例模式(Singleton)
    哈希表--HashSet<T>
    .NET 4.0中的泛型的协变和逆变
    vue-cli脚手架里如何配置屏幕自适应
    新手如何理解JS面向对象开发?
    vue轮播图插件vue-awesome-swiper的使用与组件化
    vue中sass的配置安装流程
  • 原文地址:https://www.cnblogs.com/chenxingyang/p/9747827.html
Copyright © 2020-2023  润新知