IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> socke网络通信,UDP协议,C/C++ -> 正文阅读

[C++知识库]socke网络通信,UDP协议,C/C++

??????? 在进行网络通信时,免不了使用用户数据报协议UDP协议来传输报文,UDP通信跟TCP通信的最大区别在于 它是它是不可靠的、无连接的、面向报文的,就像打电话和发短信的区别。本文将给出一个简单的,使用udp协议通信的代码,下面直接看代码。

?

一,server服务器端

??????? 1.初始化各种需要用到的参数,启动Winsock

   WSAData wsd;           //初始化信息
    SOCKET soRecv;         //接收的SOCKET
    char* pszRecv = NULL;  //接收数据的数据缓冲区指针
    int nRet = 0;          //接收数据大小
    int dwSendSize = 0;
    // MTU以太网数据帧的长度在46-1500字节之间,1500:链路层的最大传输单元
    // 单个UDP传输的最大内容为1472字节(1500-20-8)
    // 网络中标准UDP值为576字节,最好在编程中将数据长度控制在548字节以内
    int SIZEOFBUF = 4096; //接收数组大小
    int nPort = 5150;      //设置本机服务的端口号
    SOCKADDR_IN siRemote{}, siLocal{};    //远程发送机地址和本机接收机地址
    //启动Winsock
    if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
    {
        cout << "WSAStartup Error = " << WSAGetLastError() << endl;
        return 0;
    }
    else
    {
        cout << "start Success" << endl;
    }

??????? 2.创建套接字,绑定本地地址到socket

??????? int setsockopt(int sockfd, int level, int optname, void* optval, socklen_t * optlen);
??????? sockfd:要设置的套接字描述符。
?? ? ?? level:选项定义的层次。或为特定协议的代码(如IPv4,IPv6,TCP,SCTP),或为通用套接字代码(SOL_SOCKET)。
?????? optname:选项名。level对应的选项,SO_REUSEADDR让端口释放后立即就可以被再次使用。
? ? ? optval:指向某个变量的指针,该变量是要设置新值的缓冲区。可以是一个结构体,也可以是普通变量
????? optlen:optval的长度。

 siLocal.sin_family = AF_INET;
    siLocal.sin_port = htons(nPort);
    //siLocal.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    //和上一行一样
    inet_pton(AF_INET, "127.0.0.1", (void*)&siLocal.sin_addr.s_addr);
    //将点分十进制的ip地址转化为用于网络传输的数值格式

    //创建socket
    soRecv = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (soRecv == SOCKET_ERROR)
    {
        cout << "socket Error = " << WSAGetLastError() << endl;
        closesocket(soRecv);
        WSACleanup();
        return 1;
    }
    else
    {
        cout << "socket Success" << endl;
    }

    char on = 1;
    // 设置端口复用
    
    setsockopt(soRecv, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
    // 绑定本地地址到socket
    if (bind(soRecv, (SOCKADDR*)&siLocal, sizeof(siLocal)) == SOCKET_ERROR)
        //socket通用地址类型指针
        //通用地址类型长度
    {
        cout << "bind Error = " << WSAGetLastError() << endl;
        closesocket(soRecv);
        WSACleanup();
        return 0;
    }
    else
    {
        cout << "bind Success" << endl;
    }

?????????3.申请内存,等待客户端连接

???????? int recvfrom(int s, void* buf, int len, unsigned int flags, struct sockaddr* from, int* fromlen);
???????? recvfrom()用来接收远程主机经指定的socket 传来的数据, 并把数据存到由参数buf 指向的内存空间,
??????? 参数len 为可接收数据的最大长度.参数flags 一般设0, 其他数值定义请参考recv().
??????? 参数from 用来指定欲传送的网络地址, 结构sockaddr 请参考bind().
??????? 参数fromlen 为sockaddr 的结构长度。

//申请内存
    pszRecv = new char[SIZEOFBUF];
    if (pszRecv == NULL)
    {
        cout << "pszRecv new char Error " << endl;
        return 0;
    }
    else
    {
        cout << "pszRecv new char Success" << endl;
    }
    // 一直等待数据
    while (true)
    {
        dwSendSize = sizeof(siRemote);
        cout << "...开始等待数据..." << endl;
        memset(pszRecv, 0, SIZEOFBUF);//初始化为0
        //开始接受数据
        
        nRet = recvfrom(soRecv, pszRecv, SIZEOFBUF, 0, (SOCKADDR*)&siRemote, &dwSendSize);
        if (nRet == SOCKET_ERROR)
        {
            cout << "recvfrom Error " << WSAGetLastError() << endl;
            continue;
        }
        else if (nRet == 0)
        {
            cout << "recvfrom Error " << WSAGetLastError() << endl;
            continue;
        }
        else
        {
            pszRecv[128] = '\0';
            char sendBuf[20] = { '\0' };
            //将IPv4或IPv6 Internet网络地址转换为 Internet标准格式的字符串。
            inet_ntop(AF_INET, (void*)&siRemote.sin_addr, sendBuf, 16);
            cout << "收到数据大小: " << nRet << " IP地址: " << sendBuf << " 端口号: " << siRemote.sin_port << " 数据: " << pszRecv << endl;
        }
    } 
    closesocket(soRecv);//关闭socket连接
    delete[] pszRecv; 
    WSACleanup();//清理
    system("pause");
    return 0;

二.client客户端

??????? 1..初始化各种需要用到的参数,启动Winsock

  WSAData wsd;           //初始化信息
    SOCKET soSend;         //发送到的目的SOCKET
    int nRet = 0;
    int dwSendSize = 0;
    const int SIZEOFBUF = 4096;
    char recvBuf[SIZEOFBUF]={0};
    SOCKADDR_IN serverAddr{};    //服务器socket地址

    //启动Winsock
    if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
    {/*进行WinSocket的初始化,windows 初始化socket网络库,申请2,2的版本,windows socket编程必须先初始化。*/
        cout << "WSAStartup Error = " << WSAGetLastError() << endl;
        return 0;
    }
    else
    {
        cout << "WSAStartup Success" << endl;
    }

??????? 2.创建socket,设置端口号

 soSend = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (soSend == SOCKET_ERROR)
    {
        cout << "socket Error = " << WSAGetLastError() << endl;
        return 1;
    }
    else
    {
        cout << "socket Success" << endl;
    }
    //设置端口号
    int nPort = 5150; // 服务器的端口号
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(nPort);
    //serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    inet_pton(AF_INET, "127.0.0.1", (void*)&serverAddr.sin_addr.s_addr);
    //将点分十进制的ip地址转化为用于网络传输的数值格式

??????? 3.发送消息到服务器

??????? sendto(int sockfd, const void* buf, size_t len, int flags,const struct sockaddr* dest_addr, socklen_t addrlen);
??????? //函数说明
??????? //??? sockfd:socket文件描述字
??????? //??? buf:指明一个存放应用程序要发送数据的缓冲区
??????? //??? len:指明buf的长度
??????? //??? flag:一般设置为0
??????? //??? dest_addr:表示目的机的地址和端口号信息
??????? //??? addrlen:常被赋值为sizeof(struct sockaddr)

    while (1)
    {
        // 不断输入一些字符串,回车发送
        printf("input: ");
        scanf_s("%s", recvBuf, (unsigned int)sizeof(recvBuf));
        //发送数据到指定的IP地址和端口
        
        nRet = sendto(soSend, recvBuf, (int)strlen(recvBuf) + 1, 0, (SOCKADDR*)&serverAddr, sizeof(SOCKADDR));
        if (nRet == SOCKET_ERROR || nRet < 0)
        {
            cout << "sendto Error " << WSAGetLastError() << endl;
            break;
        }
        else
        {
            cout << "sendto Success!!" << endl;
        }
    }   
    closesocket(soSend);//关闭socket连接 
    WSACleanup();//清理

??????? 接下来让我们看看显示结果

?完整代码如下:socket网络通信,udp-C++文档类资源-CSDN下载

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-10-08 20:22:11  更:2022-10-08 20:24:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 4:02:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码