• 建立一个可以不停地接收客户端新的连接,但不能处理复杂的业务的C/S网络程序


    在Windows平台上主要有两个版本的Socket Api函数:
    WinSock 1.1和WinSock 2.2 , 2.2版本默认兼容1.1版本,
    1.1 winsock.h wsock32.lib winsock.dll
    2.2 winsock2.h ws2 32.lib ws2 32.dll

    2.0版本的Socket比1.1的多一些高级的功能如:
    多重协议支持:通过SPI接口支持其他协议;
    多重命名空间:根据服务与主机名选择协议
    重叠10模式:增强10吞吐量与提高性能
    分散与聚合:从多个缓冲区发送与接收数据
    有条件接受:有选择性地决定是否接受连接;
    套接字共享:多个进程共享一个套接字句柄。

    Socket套接字类型:
    比较常用的包括:流式套接字(使用TCP) ,数据报套接字(使用UDP) ,原始套接字等
    TCP与UDP各有优缺点:
    TCP :面向连接、稳定、需要资源多;
    UDP :面向无连接(一般情况下)、不稳定、需要资源少。
    用手机打电话时面向连接的,用手机发短信是面向无连接的,目前来说网络上比较常用的是TCP类型的衰接字。

    TCP与UDP的区别:
    1.基于连接与无连接
    2.对系统资源的要求(TCP较多,UDP少)
    3.UDP程序结构较简单
    4.流模式(TCP)与数据报模式(UDP)
       TCP保证数据正确性, UDP可能丢包 
       TCP保证数据顺序, UDP不保证

    具体编程时的区别
    1. socket0的参数不同
    2. UDP Server不需要淘用listen和accept
    3. UDP收发数据用sendto/recvfrom函数
    4. TCP:地址信息在connect/accept时确定
        UDP :在sendto/recvfrom函数中每次均需指定地址信息
    5. UDP : shutdown函数无效

    部分满足以下几点要求时,应该采用UDP面向数据报方式
    1.网络数据大多为短消息
    2.拥有大量Client
    3.对数据安全性无特殊要求
    4.网络负担非常重,但对响应速度要求高

    TCP类型Socket程序开发流程:
    TCP服务端: WSASartup, socket, bind, listen, accept, read, write, closesocket, WSACleanup.
    TCP客户端: WSASartup, socket, connect, read, write, closesocket, WSACleanup.

    流程图:

    这种结构虽然能不停地接收客户端新的连接,但不能处理复杂的业务。

    服务器端:

    #include<WinSock2.h>
    #include<Windows.h>
    #include<stdio.h>
    #include<iostream>
    
    #pragma comment(lib,"ws2_32.lib")
    
    int main()
    {
        WORD ver = MAKEWORD(2, 2);
        WSADATA dat;
        //WinSocket启动
        WSAStartup(ver, &dat);
    
        //建立一个socket
        SOCKET _sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //AF_INET创建一个IPV4的套接字,SOCK_STREAM面向数据流的,IPPROTO_TCP TCP
        if (INVALID_SOCKET == _sock)
        {
            printf("ERROR:建立失败!
    ");
        }
        //1.绑定
        sockaddr_in _sin = {};     //创建网络地址
        _sin.sin_family = AF_INET;
        _sin.sin_port = htons(4567); //Host to Network Short
        _sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); // IP地址 
        if (bind(_sock, (sockaddr *)&_sin, sizeof(_sin)) == SOCKET_ERROR)
        {
            printf("ERROR:绑定失败!
    ");
        }
        else
        {
            printf("TRUE:绑定成功!
    ");
        }
        //2.监听网络端口
        if (listen(_sock, 5) == SOCKET_ERROR)//第二个参数为最大等待多少人可以同时连接
        {
            printf("ERROR:监听失败!
    ");
        }
        else
        {
            printf("TRUE:监听成功!
    ");
        }
        //3.等待接收客户端连接
        sockaddr_in clientAddr = {};
        int nAddrLen = sizeof(sockaddr_in);
        SOCKET _cSOCK = INVALID_SOCKET;
        char msgBuff[] = "Hello,My is Server!
    ";
        while (1)
        {
            _cSOCK = accept(_sock, (sockaddr *)&clientAddr, &nAddrLen);
            if (_cSOCK == INVALID_SOCKET)
            {
                printf("ERROR:无效客户端SOCKET!
    ");
            }
            printf("新客户端加入:IP = %s
    ", inet_ntoa(clientAddr.sin_addr));//inet_ntoa(clientAddr.sin_addr)将接收到的IP地址转化为字符串
            //向客户端发送一条数据
            send(_cSOCK, msgBuff, strlen(msgBuff) + 1, 0);
        }
    
        //5,关闭自身的socket
        closesocket(_sock);
    
    
        //WinSocket关闭
        WSACleanup();
    
        system("pause");
        return 0;
    }

    客户端:

    #include<WinSock2.h>
    #include<Windows.h>
    #include<stdio.h>
    
    #pragma comment(lib,"ws2_32.lib")
    
    int main()
    {
        WORD ver = MAKEWORD(2, 2);
        WSADATA dat;
        WSAStartup(ver, &dat);
    
        //建立一个socket
        SOCKET _sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (INVALID_SOCKET == _sock)
        {
            printf("ERROR:建立失败!
    ");
        }
        //连接服务器
        sockaddr_in _sin = {};     //创建网络地址
        _sin.sin_family = AF_INET;
        _sin.sin_port = htons(4567); //Host to Network Short
        _sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//inet_addr("127.0.0.1"); // IP地址 
        int ret = connect(_sock, (sockaddr *)&_sin, sizeof(sockaddr_in));
        if (SOCKET_ERROR == ret)
        {
            printf("ERROR:连接失败!
    ");
        }
        else
        {
            printf("连接成功!
    ");
        }
        //接收服务器信息
        char recvBuff[256] = {};
        int nlen = recv(_sock, recvBuff, 256, 0);
        if (nlen <= 0)
        {
            printf("ERROR:接收失败!
    ");
        }
        else
        {
            printf("接收到数据:%s
    ", recvBuff);
        }
        //关闭套接字
        closesocket(_sock);
    
        //WinSocket启动
        WSAStartup(ver, &dat);
    
    
    
        //WinSocket关闭
        WSACleanup();
    
        getchar();
        return 0;
    }
  • 相关阅读:
    【转】汽车CAN总线
    【转】I2C总线协议
    【转】SPI总线协议
    【转】结构struct 联合Union和枚举Enum的细节讨论
    复合类型变量其首地址的几种表示方式
    【转】四款经典3.7v锂电池充电电路图详解
    【转】crc16几种标准校验算法及c语言代码
    【转】 CRC循环冗余校验码
    对STM32库函数中 assert 函数的认知
    【转】用宏定义代替printf函数
  • 原文地址:https://www.cnblogs.com/zhuifeng-mayi/p/10899676.html
Copyright © 2020-2023  润新知