UDP网络编程服务器与客户端代码

2023-05-16

一,通信模型
服务器:
     (1)创建socket,使用socket函数
     (2)准备通信地址,使用结构体类型
     (3)绑定socket和通信地址,使用bind函数
     (4)监听,使用listen函数
     (5)响应客户端的连接请求,使用accept函数
     (6)进行通信,使用read/write函数
     (7)关闭socket,使用close函数
客户端:
     (1)创建socket,使用socket函数
     (2)准备通信地址,使用服务器的地址
     (3)连接socket和通信地址,使用connect函数
     (4)进行通信,使用read/write函数
     (5)关闭socket,使用close函数

二,UDP发送和接收函数

1,sendto函数
    #include <sys/types.h>
    #include <sys/socket.h>
     ssize_t send(int sockfd, const void *buf, size_t len, int flags);
     ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
第一个参数:socket描述符,socket函数的返回值
第二个参数:被发送数据的首地址
第三个参数:被发送数据的大小
第四个参数:发送的标志,默认给0表示产生阻塞
第五个参数:数据接受方的通信地址
第六个参数:数据接受方通信地址的大小
返回值:成功返回实际发送的数据大小,失败返回-1
函数功能:主要用于将指定的消息发送到指定的地址上,

2,recvfrom函数
     #include <sys/types.h>
     #include <sys/socket.h>
     ssize_t recv(int sockfd, void *buf, size_t len, int flags);
     ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
第一个参数:socket描述符,socket函数的返回值
第二个参数:存放接受到数据的缓冲区首地址
第三个参数:接受的数据大小
第四个参数:接受的标志,默认给0即可
第五个参数:保存数据发送方的通信地址(来电显示)
第六个参数:通信地址的大小
返回值:成功返回实际接受的数据大小,失败返回-1
函数功能:主要用于接受指定的数据并提供来电显示的功能

三,sockaddr_in(在netinet/in.h中定义):

struct sockaddr_in
{
short sin_family;/*Address family一般来说AF_INET(地址族)PF_INET(协议族)*/
unsigned short sin_port;/*Port number(必须要采用网络数据格式,普通数字可以用htons()函数转换成网络数据格式的数字)*/
struct in_addr sin_addr;/*IP address in network byte order(Internet address)*/
unsigned char sin_zero[8];/*Same size as struct sockaddr没有实际意义,只是为了 跟SOCKADDR结构在内存中对齐*/
};

sin_family指代协议族,在socket编程中只能是AF_INET
sin_port存储端口号,在linux下,端口号的范围0~65535,同时0~1024范围的端口号已经被系统使用或保留。
sin_addr存储IP地址,使用in_addr这个数据结构
sin_zero是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节。
s_addr按照网络字节顺序存储IP地址

in_addr结构

typedef uint32_t in_addr_t;

  struct in_addr
  {
    in_addr_t s_addr;
  };

五,UDP通讯代码

1,UDP服务器代码

#include <sys/socket.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <netinet/in.h>
#include<arpa/inet.h>
int sockfd;
void sig_handler(int signo)
{
    if (signo == SIGINT)
    {
        printf("server close\n");
        close(sockfd);
        exit(1);
    }
}
void out_addr(struct sockaddr_in * clientaddr)
{
    char ip[16];
    int port;
    memset(ip, 0, sizeof(ip));
    inet_ntop(AF_INET, &clientaddr->sin_addr.s_addr, ip, sizeof(ip));
    port = ntohs(clientaddr->sin_port);
    printf("client: %s(%d)\n", ip, port);
}
void do_service()
{
    struct sockaddr_in clientaddr;
    socklen_t len = sizeof(clientaddr);
    char buffer[1024];
    memset(buffer, 0, sizeof(buffer));
    //接收客户端的数据报文
    if (recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&clientaddr, &len) < 0)
    {
        perror("recvfrom error");
    }
    else
    {
        out_addr(&clientaddr);
        printf("client send into: %s \n", buffer);
        //向客户端发送数据报文
        long int t = time(0);
        char *ptr = ctime(&t);
        size_t size = strlen(ptr) * sizeof(char);
        if (sendto(sockfd, ptr, size, 0, (struct sockaddr*)&clientaddr, len) < 0)
        {
            perror("sendto error");
        }
    }
}
int main(int argc, char* argv[])
{
    if (argc < 2)
    {
        printf("usage: %s port \n", argv[0]);
        exit(1);
    }
    if (signal(SIGINT, sig_handler) == SIG_ERR)
    {
        perror("signal sigint error");
        exit(1);
    }
    /*1.创建socket*/
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        perror("socket error");
        exit(1);
    }
    int ret;
    int opt = 1;
    //设置套接字选项SO_REUSEADDR,1.保证停用的端口可以立即使用;2.在此程序不被终止的情况下,新启动的程序绑定相同的端口也会//成功,不过此程序端口会失效。
    if ((ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) < 0)
    {
        perror("setsockopt error");
        exit(1);
    }
    /*2.调用bind函数对socket和地址进行绑定*/
    struct sockaddr_in serveraddr;
    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET; //IPv4
    serveraddr.sin_port = htons(atoi(argv[1]));//port
    serveraddr.sin_addr.s_addr = INADDR_ANY;//ip
    if (bind(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)
    {
        perror("bind error");
        exit(1);
    }
    /*3.与客户端进行数据通信*/
    while (1)
    {
        do_service();
    }
    return 0;
}

2,UDP客户端代码

#include <sys/socket.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <memory.h>
int main(int argc, char* argv[])
{
    if (argc < 3)
    {
        printf("usage: %s ip port\n", argv[0]);
        exit(1);
    }
    /*1.创建socket*/
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        perror("socket error");
        exit(1);
    }
    /*2.调用recvfrom 、sendto等函数和服务器双向通信*/
    struct sockaddr_in serveraddr;
    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(atoi(argv[2]));
    inet_pton(AF_INET, argv[1], &serveraddr.sin_addr.s_addr);
    //调用connect并不会像TCP编程中的三次握手,只是在内核在记录服务器端的一些地址信息(包括IP、端口等)
    //这样后面即使不调用sendto指定服务器的地址,而只调用send也可以向服务器发送数据。
    //建议调用connect,这样会保证客户端在接收的时候,只接收到来自指定服务器端的数据,而不会收到其它服务器的数据。
    if (connect(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)
    {
        perror("sendto error");;
        exit(1);
    }
    char buffer[1024] = "hello linux";
    //向服务器发送数据报文
    if (sendto(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)
    {
        perror("sendto error");
        exit(1);
    }
    else
    {
        //接收服务器端发送的数据报文
        memset(buffer, 0, sizeof(buffer));
        if (recv(sockfd, buffer, sizeof(buffer), 0) < 0)
        {
            perror("recv error");
            exit(0);
        }
        else
        {
            printf("%s", buffer);
        }
    }
    return 0;
}

六,用于传输结构图数据的UDP代码

1,用于结构体数据传输的服务器代码

#include  
#include  
#include  
#include  
#include  
#include 
#define MAXLINE 1024 
#define SERV_PORT 8888
struct MSG_PACK
{
    char cmd;
    char status;
    short int len;
};
struct host
{
    char UserName[20];       
    char Host[20];             
    char IP[20];               
    char PassWord [20];       
    char SubNet[512];           
    char Mode;               
    char ConState;          
    char Pin[20];               
    char ConTrol;             
    char RandPassword[10];
};
int main(void) 
{ 
    int sockfd;
    struct sockaddr_in servaddr, cliaddr;
    sockfd = socket(AF_INET, SOCK_DGRAM, 0); /* create a socket */
    /* init servaddr */
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);
    /* bind address and port to socket */
    if(bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)
    {
        perror("bind error");
        exit(1);
    }
    do_echo(sockfd, (struct sockaddr *)&cliaddr, sizeof(cliaddr));
    close(sockfd);
    return 0;
} 


void do_echo(int sockfd, struct sockaddr *pcliaddr, socklen_t clilen) 
{
    int n;
    socklen_t len;
    char mesg[MAXLINE];
    for(;;)
    {
        len = clilen;
        n = recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);  /* waiting for receive data */
        printf ("n:%d  ,  len=%d/n",n,len);
        struct MSG_PACK pocket;
        memcpy(&pocket,mesg,sizeof(struct MSG_PACK));
        printf("~~~~~~~pocket1~~~~~~~%d/n",pocket.cmd);
        printf("~~~~~~~pocket2~~~~~~~%d/n",pocket.status);
        printf("~~~~~~~pocket3~~~~~~~%d/n",pocket.len);
        struct host sHost2 ;
        memcpy(&sHost2 , mesg + sizeof(struct MSG_PACK) , sizeof(struct host));
        printf("-----sHost1-------%s/n",sHost2.UserName);
        printf("-----sHost2-------%s/n",sHost2.Host);
        printf("-----sHost3-------%s/n",sHost2.IP);
        printf("-----sHost4-------%s/n",sHost2.PassWord);
        printf("-----sHost5-------%s/n",sHost2.SubNet);
        printf("-----sHost6-------%d/n",sHost2.Mode);
        printf("-----sHost7-------%d/n",sHost2.ConState);
        printf("-----sHost8-------%s/n",sHost2.Pin);
        printf("-----sHost9-------%d/n",sHost2.ConTrol);
        printf("-----sHost10-------%s/n",sHost2.RandPassword);
        n = sendto(sockfd, mesg, n, 0, pcliaddr, len);      /* 回发给client */
    }
} 

2,用于结构体数据传输的客户端代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

#define minornode                 0    //从节点向主节点发送连接请求
#define hostnode_return           1    //主节点响应从节点的请求
#define minornode_change          2    //从节点向主节点发送更新请求
#define hostnode_returnchange     3    //主节点响应更新请求

    //包头的定义
    struct MSG_PACK
    {
        char cmd;
        char status;
        short int len;
    };
    


    //定义host
  struct host
  {
          char UserName[20];        
        char Host[20];              
        char IP[20];                
        char PassWord [20];        
        char SubNet[512];            
        char Mode;                
        char ConState;           
        char Pin[20];                
        char ConTrol;              
        char RandPassword[10];
  };

int main()
{
    char sentbuf[1024];
    
    struct host newhost;
    
    memset(&newhost,0,sizeof(struct host));
    
      strcpy(newhost.UserName,"aaaa");
    strcpy(newhost.Host,"www");
    strcpy(newhost.IP,"192.168.8.103");
    strcpy(newhost.PassWord,"1111");
    strcpy(newhost.SubNet,"255.255.255.0");
    newhost.Mode=0;
    newhost.ConState=1;
    strcpy(newhost.Pin,"20");
    newhost.ConTrol=0;
    strcpy(newhost.RandPassword,"122122");
    //printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@ %s %s %s %s %s %d %d %s %d %s @@@@@@@@@@@@@@@@@@@@@@@@@@@@ ",newhost.UserName,newhost.Host,newhost.IP,newhost.PassWord,newhost.SubNet,newhost.Mode,newhost.ConState,newhost.Pin,newhost.ConTrol,newhost.RandPassword);
    
    struct MSG_PACK newpack;
    newpack.cmd=1;
    newpack.status=1;
    newpack.len=sizeof(newhost);
    //printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@ %d %d %d @@@@@@@@@@@@@@@@@@@@@@@@@@@ ",newpack.cmd,newpack.status,newpack.len);
    memcpy(sentbuf,&newpack,sizeof(struct MSG_PACK));
    memcpy(sentbuf+sizeof(struct MSG_PACK),&newhost,sizeof(struct host));
    int iLen = sizeof(struct MSG_PACK)+ sizeof(struct host);
    printf("-=-=-=-=-=-=-=-=-=-=-=-=%d  ",iLen);
    int sock; 
    //sendto中使用的对方地址
    struct sockaddr_in servaddr;
    //在recvfrom中使用的对方主机地址
    struct sockaddr_in fromAddr;

  
    unsigned int fromLen;
    char recvBuffer[1024];
    sock = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
    memset(&servaddr,0,sizeof(servaddr));
    servaddr.sin_family=AF_INET;
    servaddr.sin_addr.s_addr=inet_addr("192.168.8.200");
    servaddr.sin_port = htons(8000);
    if(sendto(sock,sentbuf,iLen,0,(struct sockaddr*)&servaddr,sizeof(servaddr)) != iLen)
    {
         perror("sendto error"); 
         close(sock);
         exit(1);
    }
    fromLen = sizeof(fromAddr);
    if(recvfrom(sock,recvBuffer,1024,0,(struct sockaddr*)&fromAddr,&fromLen)<0)
    {
         perror("recvfrom error"); 
         close(sock);
         exit(1);
    }
    struct MSG_PACK pocket;
    memcpy(&pocket , recvBuffer , sizeof(struct MSG_PACK));
    
    printf("-----pocket1------->%d ",pocket.cmd);
    printf("-----pocket2------->%d ",pocket.status);
    printf("-----pocket3------->%d ",pocket.len);
    
    struct host sHost2 ;
    memcpy(&sHost2 , recvBuffer + sizeof(struct MSG_PACK) , sizeof(struct host));
    printf("&&&&&&&&&&&&&&&&&&&& -----sHost1------->%s ",sHost2.UserName);
    printf("-----sHost2------->%s ",sHost2.Host);
    printf("-----sHost3------->%s ",sHost2.IP);
    printf("-----sHost4------->%s ",sHost2.PassWord);
    printf("-----sHost5------->%s ",sHost2.SubNet);
    printf("-----sHost6------->%d ",sHost2.Mode);
    printf("-----sHost7------->%d ",sHost2.ConState);
    printf("-----sHost8------->%s ",sHost2.Pin);
    printf("-----sHost9------->%d ",sHost2.ConTrol);
    printf("-----sHost10------->%s &&&&&&&&&&&&&&&&&&&& ",sHost2.RandPassword);
    
    close(sock);
    return 0;
}

​

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

UDP网络编程服务器与客户端代码 的相关文章

  • mac下 ndk_build: command not found

    参考 http blog csdn net greenbird811 article details 7543305 在mac下调用ndk build c代码文件提示错误 fix 1 启动终端Terminal 2 进入当前用户的home目录
  • 公司分配IP地址,求主机号码的最小值和最大值。

    问题描述如下 xff1a 姐 xff1a 注意减去2的实际意义 xff1a 网络地址后的第一个主机地址是本网段的网络地址192 168 0 0 xff0c 最 后一个主机地址是本网段的广播地址192 168 255 255
  • Erlang入门

    64 author sunxu 64 copyright C 2023 lt COMPANY gt 64 doc 64 end Created 16 2月 2023 22 16 module test author 34 sunxu 34
  • IPv4地址、IPv6地址和Mac地址的位数

    xff08 1 xff09 IPv4的地址是32位 xff0c 用点分十进制表示 xff0c 每八位划分 xff0c 也就是四个0 255的十进制数 xff0c 这是很常见的 xff08 2 xff09 IPv6的地址是128位 xff0c
  • 用C#连接数据库的方法

    连接SQL Server数据库的方法 xff1a 1 在程序中引用System Data SqlClient命名空间 2 编写连接字符串 xff0c 格式为 xff1a Data Source 61 服务器名称 Initial Catalo
  • gcc 不支持 //注释的解决

    这段时间用slickedit写代码 xff08 windows平台下 xff0c 装了Cygwin xff09 xff0c 编译器用的gcc xff0c 但是有个问题就是用 34 34 写注释的时候 xff0c 编译的时候有错 xff1a
  • python实现按照文件名称进行文件分类

    问题 xff1a 大量名称中带有数字的图片 视频 xff0c 根据名称中数字按照一定的等差数列来排序 xff0c 并且放入指定对应的文件夹中 span class token keyword import span os span clas
  • 【深度学习】Yolov3详解笔记及Pytorch代码

    Yolov3详解笔记及Pytorch代码 预测部分网络结构backbone xff1a Darknet 53output预测结果的解码 训练部分计算loss所需参数pred是什么target是什么loss的计算过程 预测部分 网络结构 DB
  • 【深度学习】各种卷积的理解笔记(2D,3D,1x1,可分离卷积)

    卷积 1 2D卷积单通道版本多通道版本 2 3D卷积3 1x1卷积作用应用 4 卷积算法5 可分离卷积空间可分离卷积深度可分离卷积 1 2D卷积 卷积的目的是从输入中提取有用的特征 在图像处理中 xff0c 卷积可以选择多种不同的滤波器 每
  • 【深度学习】(2+1)D模型框架结构笔记

    xff08 2 43 1 xff09 D 模型框架结构笔记 SpatioTemporalConv模块结构SpatioTemporalResBlock模块结构SpatioTemporalResLayer模块结构2Plus1DNet Spati
  • 【机器学习】LR回归(逻辑回归)和softmax回归

    LR回归 xff08 逻辑回归 xff09 和softmax回归 1 LR回归Logistic回归的函数形式Logistic回归的损失函数Logistic回归的梯度下降法Logistic回归防止过拟合Multinomial Logistic
  • 【深度学习】时间注意力模块与空间注意力模块

    注意力模块 通道 xff08 时间 xff09 注意力模块空间注意力模块 通道 xff08 时间 xff09 注意力模块 为了汇总空间特征 xff0c 作者采用了全局平均池化和最大池化两种方式来分别利用不同的信息 输入是一个 H W C 的
  • 【机器学习】机器学习与统计分布的关系

    这里写目录标题 1 常见的统计学分布1 xff09 离散分布a 伯努利分布b 二项分布c 泊松分布 2 xff09 连续分布a 正态分布 xff08 高斯分布 xff09 b 均匀分布 为什么我们喜欢用 sigmoid 这类 S 型非线性变
  • AKKA入门

    1 Guardian java package com example demo import akka actor typed javadsl ActorContext import akka actor typed ActorRef i
  • 【深度学习】深入理解Batch Normalization批标准化

    Batch Normalization 1 Internal Covariate Shift 问题2 BatchNorm的本质思想1 xff09 函数图像说明2 xff09 算法3 xff09 引入参数恢复表达能力4 xff09 公式 3
  • Autolabelimg自动标注工具

    目录 前言 一 工具原理和功能 1 原理 2 功能列表 二 实战 1 下载与安装 2 配置环境 3 开始使用 4 导入模型 5 选择标注类别 6 进行自动标注 三 总结 前言 在做机器视觉有监督方面 通常会面对很多数据集 xff0c 然后去
  • anchor base,anchor free和基于分割的图像检测

    目录 1 anchor base 2 anchor free 3 基于分割 reference 1 anchor base 什么是anchor based的目标检测方法呢 如果要让你定一个规则去一个图片上框一个物体 xff0c 你会怎么做呢
  • 我的2013:从北京到石家庄的软件开发历程

    记得是正月初八那天早上离开了老家 xff0c 坐上了开往北京的大巴车去北京准备新 的一年的奋斗 xff0c 车票120元了 涨价了20 xff0c 而且还没有地方报销去了 gt lt 因为年底的时候已经离职了 考虑到各公司部门人员 xff0
  • [机器学习] ML重要概念:梯度(Gradient)与梯度下降法(Gradient Descent)

    引言 机器学习栏目记录我在学习Machine Learning过程的一些心得笔记 xff0c 涵盖线性回归 逻辑回归 Softmax回归 神经网络和SVM等等 xff0c 主要学习资料来自网上的免费课程和一些经典书籍 xff0c 免费课程例
  • TPMS胎压芯片选择:英飞凌SP370、英飞凌SP40、飞思卡尔FXTH87

    简介TPMS Tire Pressure Monitoring System xff08 TPMS xff09 xff0c 轮胎压力监测系统 xff0c TPMS的作用是在汽车行驶过程中对轮胎气压进行实时自动监测 xff0c 并对轮胎漏气和

随机推荐