UDP通信实验

实验设备:   

目标系统:Windows

软件工具:vs2022/vc6/dev 

实验要求:

  1. 完成UDP服务端和客户端的程序编写;
  2. 分别实现UDP一对一通信和广播通信功能。

实验内容:-static-libgcc

一对一通信

服务器和客户端编程详细步骤:

1、加载/释放Winsock库,创建套接字(WSAStartup()/socket())。

加载方法:

WSADATA wsa;

/*初始化socket资源*/

if (WSAStartup(MAKEWORD(1,1),&wsa) != 0)

{

    return;   //代表失败

}

释放方法:

WSACleanup();

2、绑定IP地址、端口等信息到socket上

server.sin_family = AF_INET;

          server.sin_port = htons(12345);   本地监听端口

          server.sin_addr.s_addr = inet_addr(ip);

    

3、发送数据。用返回的套接字和客户端进行通信(函数recvfrom()sendto())  

  sendto():

int ret = recvfrom(int sockfd,void *buf,size_t len,0, struct sockaddr *to ,   int fromlen);

第一个参数为服务端的udp监听套接字

第二个参数为发送数据的缓冲区

第三个参数为缓存区的大小

第四个参数一般为0;

第五个参数一般为:记录地址信息,ip信息的结构体 。

第六个参数为:第五个参数的大小。

返回值:成功返回实际发送出去的信息的字节数,失败返回-1

recvfrom():

int ret = recvfrom(int sockfd,void *buf,size_t len,0, struct sockaddr *from,socket_t *fromlen);

第一个参数为服务端的udp监听套接字

第二个参数为接收数据的缓冲区

第三个参数为缓存区的大小

第四个参数一般为0;

第五个参数一般为:记录地址信息,ip信息的结构体 。

第六个参数为:第五个参数的大小,取地址。

返回值:成功返回接收到的信息的字节数,失败返回-1

服务端: 等待客户端接入.char buf[1024].

接收数据:recvfrom(Command_Sock,buf, …)

发送数据:sendto(Command_Sock,buf, …)

客户端: 请求与服务端连接.char buf[1024].

            发送数据:sendto(Client_Sock,buf, …)

          或

           接收数据:recvfrom(Client_Sock,buf, …)

4、关闭套接字,关闭加载的套接字库(closesocket()/WSACleanup())。

closesocket(Listen_Sock)

closesocket(Command_Sock)

注意:在dev里面编译会出现报错,需要在项目管理—参数—添加libws2_32.a动态库,该库在C:\Program Files (x86)\Dev-Cpp\MinGW64\x86_64-w64-mingw32\lib\libws2_32.a路径下。

代码执行结果

 

服务器端完整代码

 

#include<stdio.h>

#include<stdlib.h>

#include<Winsock2.h>

int main (int agrc,char*argv[])

{

     SOCKET socket1;

     WSADATA wsaData;

     int ErrorCode;

     if(WSAStartup(MAKEWORD(2,1),&wsaData))// windows socket dll;

     {

        printf("Winsock启动失败!!\n");

        WSACleanup();

        return 0;

     }

   

     printf("Winsock start...\n");

     const char* ip="127.0.0.1";

     struct sockaddr_in server;

     int len = sizeof(server);

     server.sin_family = AF_INET;

     server.sin_port = htons(12345); 

     server.sin_addr.s_addr = inet_addr(ip);

   

     socket1 = socket(AF_INET,SOCK_DGRAM,0);

     while (1)

     {

        char buffer[1024] = "/0";

        printf("请输入要发送的信息:\n");

        scanf("%s",buffer);

        //printf("%s",buffer);

        if(strcmp(buffer,"bye")==0)

        {

           printf("exit,bye!!\n");

           Sleep(100);

           closesocket(socket1);

           break;

        }

      

        if(sendto(socket1,buffer,sizeof(buffer),0,(struct sockaddr*)&server,len)!=SOCKET_ERROR)

        {

            printf("发送完毕\n");

            Sleep(100);

            if(recvfrom(socket1,buffer,sizeof(buffer),0,(struct sockaddr*)&server,&len) != SOCKET_ERROR)

                printf("recevie from server: %s\n",buffer);                                          

        } 

     }

     closesocket(socket1);

     system("pause");

     return 0;

}

客户端完整代码

#include<stdio.h>

#include<stdlib.h>

#include<Winsock2.h>

int main (int agrc,char*argv[])

{

     SOCKET socket1;

     WSADATA wsaData;

     int ErrorCode;

     if(WSAStartup(MAKEWORD(2,1),&wsaData))// windows socket dll;

     {

        printf("Winsock启动失败!!\n");

        WSACleanup();

        return 0;

     }

   

     printf("Winsock start...\n");

     struct sockaddr_in local;

     struct sockaddr_in client;

     int len = sizeof(client);

     local.sin_family = AF_INET;

     local.sin_port = htons(12345);  //the port need listened

     local.sin_addr.s_addr = INADDR_ANY; //localhost

   

     socket1 = socket(AF_INET,SOCK_DGRAM,0);

     bind(socket1,(struct sockaddr*)&local,sizeof(local));

   

     while (1)

     {

        char buffer[1024] = "/0";

        printf("等待来自服务器发送的信息:\n");

        if(recvfrom(socket1,buffer,sizeof(buffer),0,(struct sockaddr*)&client,&len) != SOCKET_ERROR)

        {

                printf("接收到的信息为: [%s]---%s\n",inet_ntoa(client.sin_addr),buffer);

                //send sth to the client

                sendto(socket1,buffer,sizeof(buffer),0,(struct sockaddr*)&client,len);

        }                                            

     }

     closesocket(socket1);

     system("pause");

     return 0;

}

UDP广播通信

服务器和客户端编程详细步骤:

分析

广播通信是一对多的通信方式,会将消息分发给整个局域网内的所有主机,客户端需要绑定服务端广播使用的端口才能够接收到广播消息。广播地址以192.168.22.3网段为例:192.168.22.255 代表该网段的广播地址,发送给该地址的数据包被所有主机接收。

sendto("你好",192.168.22.255);

发送端

  1. 建立套接字;
  2. 设置该套接字允许进行广播;

     3、将数据发送到广播地址中:sendto(buf,192.168.22.255);

     4、关闭

接收端(服务器)

  1. 建立套接字;
  2. 绑定广播ip地址(192.168.22.255)和端口号9999
  3. 接收数据
  4. 关闭

具体实现过程

广播发送端

1创建数据报套接字 UDP

int socketfd = socket(AF_INET,SOCK_DGRAM,0);

2、设置socketfd套接字文件描述符的属性为 广播 。

int on=1;

setsockopt(sockfd , SOL_SOCKET,SO_BROADCAST,&on, sizeof(on));

3、发送数据 ,指定接收方为广播地址

struct sockaddr_in sendAddr;

sendAddr.sin_family = AF_INET;

sendAddr.sin_port = htons(9999);

sendAddr.sin_addr.s_addr = inet_addr("192.168.22.255");

sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&sendAddr,sizeof(sendAddr));

4、关闭

close();

广播接收方(服务器端)

1创建用户数据报套接字

int socketfd = socket(AF_INET,SOCK_DGRAM,0);

2、绑定(192.168.14.255)广播IP地址和端口号 (10000)

注意:绑定的端口必须和发送方指定的端口相同

struct sockaddr_in ownAddr;

ownAddr.sin_family = AF_INET;

ownAddr.sin_port = htons(10000);

ownAddr.sin_addr.s_addr = htonl(INADDR_ANY);//INADDR_ANY(0.0.0.0) 代表本机所有的地址

3、接收数据

recvfrom;

4、关闭套接字

close();
 

源代码:

发送端

#include <stdio.h>

#include <unistd.h>

#include <string.h>

#include <Winsock2.h>

#include <windows.h>

 

#define GUANG_IP  "192.168.22.255"

#define GUANG_PORT   9999

int main()

{

    //建立套接字

    int socket_fd = socket(AF_INET,SOCK_DGRAM,0);

    if(socket_fd < 0)

    {

       perror("sokcet fail");

       return -1;

    }

   

   

    //设置广播属性

    int on=1;

    setsockopt(socket_fd , SOL_SOCKET,SO_BROADCAST,&on, sizeof(on)); 

   

    //给广播地址发送数据

    struct sockaddr_in send_addr;

    send_addr.sin_family = AF_INET;

    send_addr.sin_port = htons(GUANG_PORT);

    send_addr.sin_addr.s_addr = inet_addr(GUANG_IP);//广播地址

   

    char buf[1024] = {0};

    while(1)

    {  

       bzero(buf,sizeof(buf));

       scanf("%s",buf);

       //发送的是实际的长度

       sendto(socket_fd,buf,strlen(buf),0,(struct sockaddr *)&send_addr,sizeof(send_addr));

    }

   

    //关闭套接字

    close(socket_fd);

}

接收端

#include <stdio.h>

#include <unistd.h>

#include <string.h>

#include <Winsock2.h>

#include <windows.h>

#define GUANG_IP  "192.168.22.255"

#define GUANG_PORT   9999

int main()

{

    //建立套接字

    int socket_fd = socket(AF_INET,SOCK_DGRAM,0);

    if(socket_fd < 0)

    {

       perror("sokcet fail");

       return -1;

    }

   

    //绑定广播地址

    struct sockaddr_in my_addr;

    my_addr.sin_family = AF_INET;

    my_addr.sin_port = htons(GUANG_PORT);

    my_addr.sin_addr.s_addr = htonl(INADDR_ANY);//INADDR_ANY本机任意IP地址--常用方法

    bind(socket_fd,(struct sockaddr *)&my_addr,sizeof(my_addr));

   

    char buf[1024] = {0};

    int ret;

    struct sockaddr_in recv_addr;

    socklen_t addrlen = sizeof(recv_addr);

    while(1)

    {  

       bzero(buf,sizeof(buf));//清空缓冲区

       ret = recvfrom(socket_fd,buf,sizeof(buf),0,(struct sockaddr *)&recv_addr,&addrlen);

       char *ip = inet_ntoa(recv_addr.sin_addr);

       int port = ntohs(recv_addr.sin_port);

       printf("[ip:%s port:%d] buf:%s ret:%d\n",ip,port,buf,ret);

    }

   

    //关闭套接字

    close(socket_fd);

}

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐