• WinSocket编程笔记(五)


    三.UDP的Socket编程

    先前的socket服务器端与客户端需要建立连接才能通信,因此是面向连接的基于TCP的Socket。而这里的基于UDP的Socket是面向无连接的,也就是说不必调用 listen() 和 accept() 函数,那么connect()函数也就一样没有使用的必要了。

    UDP新增的函数:

    1.发送数据sendto() 函数(相比send()函数多了最后面两个参数)

    函数原型:

    int sendto(int s, const void * buf, int len, unsigned int flags, const struct sockaddr * to, int addrlen);
    • sock:用于传输UDP数据的套接字;
    • buf:保存待传输数据的缓冲区地址;
    • len:带传输数据的长度(以字节计);
    • flags:可选项参数,若没有可传递0;
    • to:存有目标地址信息的 sockaddr 结构体变量的地址;
    • addrlen:传递给参数 to 的地址值结构体变量的长度;

    定义实例:

    sendto(sock, buffer, strlen(buffer), 0, (struct sockaddr*)&servAddr, sizeof(servAddr));

    2.接收数据recvfrom() 函数

    函数原型:

    int recvfrom(SOCKET sock, char *buf, int nbytes, int flags, const struct sockaddr *from, int *addrlen);
    • sock:用于接收UDP数据的套接字;
    • buf:保存接收数据的缓冲区地址;
    • nbytes:可接收的最大字节数(不能超过buf缓冲区的大小);
    • flags:可选项参数,若没有可传递0;
    • from:存有发送端地址信息的sockaddr结构体变量的地址;
    • addrlen:保存参数 from 的结构体变量长度的变量地址值;

    定义实例:

    recvfrom(sock, buffer, BUF_SIZE, 0, &clntAddr, &nSize);

    基于UDP的Socket编程

    服务器:

    #include <cstdio>
    #include<iostream>
    #include<string>
    #include<WinSock2.h>
    #pragma comment(lib,"ws2_32.lib")
    using namespace std;
    const int PORT = 8000;
    #define BUF_SIZE 100
    
    int main(){
    WORD sockVersion = MAKEWORD(2, 2);
    
        WSADATA data;
    
        if (WSAStartup(sockVersion, &data) != 0)
    
        {
    
            return 1;
    
        }
    SOCKET ListenSocket = socket(AF_INET,SOCK_STREAM,0);
    SOCKADDR_IN ListenAddr;
    ListenAddr.sin_family=AF_INET;
    ListenAddr.sin_addr.S_un.S_addr=INADDR_ANY;
    ListenAddr.sin_port=htons(PORT);
    int n;
    n=bind(ListenSocket,(LPSOCKADDR)&ListenAddr,sizeof(ListenAddr));
    if(n==SOCKET_ERROR){
    cout<<"端口绑定失败!"<<endl;
    return -1;
    }
    else{
    cout<<"端口绑定成功:"<<PORT<<endl;
    }
    //接收客户端
    SOCKADDR clntAddr;  //客户端地址信息
    int nSize = sizeof(SOCKADDR);
    char buffer[BUF_SIZE];  //缓冲区
    while(1){
        int strLen = recvfrom(ListenSocket, buffer, BUF_SIZE, 0, &clntAddr, &nSize);
        sendto(ListenSocket, buffer, strLen, 0, &clntAddr, nSize);
    }
    closesocket(ListenSocket);
     WSACleanup();
     return(0);
    }

    客户端:

    #include <cstdio>
    #include<iostream>
    #include<string>
    #include<WinSock2.h>
    #pragma comment(lib,"ws2_32.lib")
    using namespace std;
    const int PORT = 8001;
    #define BUF_SIZE 100
    
    int main(){
    WORD sockVersion = MAKEWORD(2, 2);
    
        WSADATA data;
    
        if (WSAStartup(sockVersion, &data) != 0)
    
        {
    
            return 1;
    
        }
    SOCKET ListenSocket = socket(AF_INET,SOCK_STREAM,0);
    SOCKADDR_IN ListenAddr;
    ListenAddr.sin_family=AF_INET;
    ListenAddr.sin_addr.S_un.S_addr=INADDR_ANY;
    ListenAddr.sin_port=htons(PORT);
    int n;
    n=bind(ListenSocket,(LPSOCKADDR)&ListenAddr,sizeof(ListenAddr));
    if(n==SOCKET_ERROR){
    cout<<"端口绑定失败!"<<endl;
    return -1;
    }
    else{
    cout<<"端口绑定成功:"<<PORT<<endl;
    }
    //服务器地址信息
        sockaddr_in servAddr;
        memset(&servAddr, 0, sizeof(servAddr));  //每个字节都用0填充,可省略
        servAddr.sin_family = PF_INET;
        servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
        servAddr.sin_port = htons(1234);
        //不断获取用户输入并发送给服务器,然后接受服务器数据
        sockaddr fromAddr;
        int addrLen = sizeof(fromAddr);
        while(1){
            char buffer[BUF_SIZE] = {0};
            printf("Input a string: ");
            gets(buffer);
            sendto(ListenSocket, buffer, strlen(buffer), 0, (struct sockaddr*)&servAddr, sizeof(servAddr));
            recvfrom(ListenSocket, buffer, BUF_SIZE, 0, &fromAddr, &addrLen);
            cout<<"Message from server:"<<buffer<<endl;
        }
    closesocket(ListenSocket);
     WSACleanup();
     return(0);
    }

    服务器端接收到客户端信息以后发回给客户端,客户端打印接收到的消息

    运行结果

    (待续)

    [Sign]做不出ctf题的时候很痛苦,你只能眼睁睁看着其他人领先你
  • 相关阅读:
    HTTP Continuation or nonHTTP traffic 数据包
    linuxTcp IP协议栈源码阅读笔记(转)
    使用Windows命令行启动服务
    数据库集群
    ShellExecute
    oracle 中数据库完全导入导出:cmd命令行模式
    理解ORACLE数据库字符集
    asp.net 编码设置
    ShellExecute与ShellExecuteEx的用法
    C++用位运算实现循环移位
  • 原文地址:https://www.cnblogs.com/echoDetected/p/12732145.html
Copyright © 2020-2023  润新知