基于UDP的winsock同步通讯

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hhhuang1991/article/details/80071751

一、代码实现

服务端

#include "stdafx.h"
#include <iostream>
#include <Winsock2.h>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;

int main()
{
    WSADATA wsaData;
    SOCKET s;
    SOCKADDR_IN server;
    char sendbuf[1024], recvbuf[1024];
    int err = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (-1 == err)
    {
        cerr << "WSAStartup调用失败." << endl;
        goto Error;
    }
    //创建socket
    s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (INVALID_SOCKET == s)
    {
        cerr << "SOCKET创建失败." << endl;
        goto Error;
    }
    //绑定本地地址
    server.sin_family = AF_INET;
    inet_pton(AF_INET, "127.0.0.1", &server.sin_addr);
    server.sin_port = htons(5000);
    err = bind(s, (const sockaddr*)&server, sizeof server);
    if (SOCKET_ERROR == err)
    {
        cerr << "绑定失败." << endl;
        goto Error;
    }
    //接收客户端的数据
    while (true)
    {
        SOCKADDR_IN fromaddr;
        int len = sizeof(fromaddr);
        memset(recvbuf, 0, 1024);
        int iResult = recvfrom(s, recvbuf, 1024, 0, (sockaddr*)&fromaddr, &len);
        if (iResult > 0)
        {
            char ip[16];
            memset(ip, 0, sizeof ip);
            inet_ntop(AF_INET, &fromaddr.sin_addr, ip, 16);
            cout << "接收来自" << ip << "的数据:" << recvbuf << endl;
            //发送数据
            memset(sendbuf, 0, 1024);
            strcpy_s(sendbuf, "Hello Client");
            int err = sendto(s, sendbuf, 13, 0, (const sockaddr*)&fromaddr, sizeof fromaddr);
            if (SOCKET_ERROR == err)
            {
                cerr << "发送失败." << endl;
                goto Error;
            }
        }
    }
Error:
    if (INVALID_SOCKET == s)
        closesocket(s);
    WSACleanup();
    getchar();
    return 0;
}

客户端


#include "stdafx.h"
#include <iostream>
#include <WinSock2.h>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
int main()
{
    WSADATA wsaData;
    SOCKET s;
    SOCKADDR_IN server;
    SOCKADDR_IN fromaddr;
    int len = sizeof(fromaddr);
    char sendbuf[1024], recvbuf[1024];
    int err = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (-1 == err)
    {
        cerr << "WSAStartup调用失败." << endl;
        goto Error;
    }
    //创建socket
    s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (INVALID_SOCKET == s)
    {
        cerr << "SOCKET创建失败." << endl;
        goto Error;
    }
    //给指定的服务端发送数据
    server.sin_family = AF_INET;
    inet_pton(AF_INET, "127.0.0.1", &server.sin_addr);
    //server.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");  //inet_pton InetPton
    server.sin_port = htons(5000);
    memset(sendbuf, 0, 1024);
    strcpy_s(sendbuf, "Hello Server");  //strcpy_s
    err = sendto(s, sendbuf, 13, 0, (const sockaddr*)&server, sizeof(server));
    if (SOCKET_ERROR == err)
    {
        cerr << "发送失败.";
        goto Error;
    }
    while (true)
    {
        memset(recvbuf, 0, 1024);
        int iResult = recvfrom(s, recvbuf, 1024, 0, (sockaddr*)&fromaddr, &len);
        if (SOCKET_ERROR == iResult)
        {
            cerr << "接收失败.";
            goto Error;
        }
        else if (iResult > 0)
        {
            //inet_ntop InetNtop
            //cout << "接收来自" << inet_ntoa(fromaddr.sin_addr) << "的数据:" << recvbuf << endl;
            char ip[16];
            memset(ip, 0, 16);
            inet_ntop(AF_INET, &fromaddr.sin_addr, ip, 16);
            cout << "接收来自" << ip << "的数据:" << recvbuf << endl;
        }
    }

Error:
    if (INVALID_SOCKET == s)
        closesocket(s);
    WSACleanup();
    getchar();
    return 0;
}

二、总结

  • inet_pton和inet_ntop
    在VS2015中使用inet_addr和inet_ntoa网络地址转换函数会报错,因此采用最新的替代函数inet_pton和inet_ntop。 这两个函数是随IPv6出现的函数,对于IPv4地址和IPv6地址都适用,函数中p和n分别代表表达(presentation)和数值(numeric)。地址的表达格式通常是ASCII字符串,数值格式则是存放到套接字地址结构的二进制值。
/**
* @brief 将点分十进制的ip地址转化为用于网络传输的数值格式
* @return 若成功则为1,若输入不是有效的表达式则为0,若出错则为-1
*/ 
int inet_pton(int family, const char *strptr, void *addrptr);    
/**
* @brief 将数值格式转化为点分十进制的ip地址格式  
* @return 若成功则为指向结构的指针,若出错则为NULL  
*/
const char * inet_ntop(int family, const void *addrptr, char *strptr, size_t len);   
  • 服务器端如何知道客户端的IP和端口信息

1.客户端向服务端发送消息,服务端通过recvfrom收到消息和客户端的地址信息,然后服务端就可以给这个客户端地址发送消息。

猜你喜欢

转载自blog.csdn.net/hhhuang1991/article/details/80071751