UDP通讯方式

Wesley13
• 阅读 651

简介

一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,它一旦把应用的程序发送给网络层之后不保留数据的备份。但是因为没有很多安全性的校验使得它的传输速率特别的快。 UDP提供了无连接通信,且不对传送数据包进行可靠性保证,适合于一次传输少量数据,UDP传输的可靠性由应用层负责。

###所需的结构和方法 *sockaddr_in结构体

#include <netinet/in.h>
struct sockaddr_in {
    short            sin_family;   // e.g. AF_INET
    unsigned short   sin_port;     // e.g. htons(3490)
    struct in_addr   sin_addr;     // see struct in_addr, below
    char             sin_zero[8];  // zero this if you want to
};
struct in_addr {
    unsigned long s_addr;  // load with inet_aton()
};
  • sockaddr_in不管是tcp和UDP通讯都必然需要的一个结构。AF_INET是internet地址族,包括了tcp、udp什么的,
  • sin_port 通讯的端口
  • sin_addr 保留了通讯的IP地址
  • sin_zero 没有实际意义,只是为了 跟SOCKADDR结构在内存中对齐 ####socket方法

socket(int socket_family, int socket_type, int protocol);

  • domain

AF_UNIX,AF_LOCAL 本地通讯

AF_INET IPV4网络规约

AF_INET6 IPV6网络规约

  • type

SOCK_STREAM 提供可靠的连接方式(TCP)

SOCK_DGRAM 提供不可靠非连接的通讯方式(UDP)

  • protocol

IPPROTO_IP 相当于指定的参数为零

IPPROTO_TCP 表明采用TCP规约

IPPROTO_UDP 表示采用UDP规约

####bind方法 bind标准定义是指绑定一个名称到socket,sockfd是表示一个socket所创建的对象,sockaddr表示是该绑定的地址和socket所指向的地址分配空间大小

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

####recvfrom 接收一个数据报并保存源地址

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);

  • ssockfd:标识一个已连接套接口的描述字。
  • buf:接收数据缓冲区。
  • len:缓冲区长度。
  • flags:调用操作方式。
  • src_addr:(可选)指针,指向装有源地址的缓冲区。
  • addrlen:(可选)指针,指向from缓冲区长度值。

该函数返回接收的字节数,如果出现错误返回-1,倘若对方关闭链路则返回0;

服务端

socket()->bind()->recvfrom()->sendto()

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define BUFLEN 512//最大的缓冲长度 
#define PORT 8888//监听数据的端口
void die(char *s){
    perror(s);
    exit(1);
}
int main(int argc, char const* argv[])
{
    struct sockaddr_in si_me,si_other;
    int s,i,slen=sizeof(si_other),recv_len;
    char buf[BUFLEN];
    //创建一个UDP的socket
    if((s=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))==-1){
        die("socket");
    }
    //将这个结构清零
    memset((char *)&si_me,0,sizeof(si_me));

    si_me.sin_family=AF_INET;
    si_me.sin_port=htons(PORT);
    si_me.sin_addr.s_addr=htonl(INADDR_ANY);
    //指定需要绑定的端口
    if(bind(s,(struct sockaddr*)&si_me,sizeof(si_me))==-1){
         die("bind");
    }
    while(1){
        printf("Waiting for data...");
        fflush(stdout);
        //从远程接收数据,这是一个堵塞的函数,直到接触到数据为止
        if((recv_len=recvfrom(s,buf,BUFLEN,0,(struct sockaddr*)&si_other,&slen))==-1)
        {
            die("recvfrom()");
        }
        //打印客户端的信息及其相关的信息
        printf("Received packet from %s:%d\n",inet_ntoa(si_other.sin_addr),ntohs(si_other.sin_port));
        printf("recv Data:%s\n",buf);
        //将接收到的数据进行发送
        if(sendto(s,buf,recv_len,0,(struct sockaddr*)&si_other,slen)==-1){
            die("sendto()");
        }
        //重置所有的数据
        bzero(&buf,sizeof(buf));
    }
    close(s);//关闭socket
    return 0;
}

Waiting for data...Received packet from 127.0.0.1:64687

recv Data:send data

client端

socket()->sendto()/recvfrom()

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define SERVER "127.0.0.1"
#define BUFLEN 512//缓冲区的大小
#define PORT 8888//发送数据的端口
void die(char *s){
    perror(s);
    exit(1);
}
int main(int argc, char const* argv[])
{
    struct sockaddr_in si_other;
    int s,i,slen=sizeof(si_other);
    char buf[BUFLEN];
    char message[BUFLEN];
    if((s=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))==-1)
    {
        die("socket");
    }
    memset((char *)&si_other,0,sizeof(si_other));
    si_other.sin_family=AF_INET;
    si_other.sin_port=htons(PORT);

    if(inet_aton(SERVER,&si_other.sin_addr)==0){
         fprintf(stderr,"inet_atom() failed\n");
         exit(1);
    }
    while(1){
        printf("Enter message:");
        gets(message);
        //发送数据
        if(sendto(s,message,strlen(message),0,(struct sockaddr *)&si_other,slen)==-1){
            die("sendto()");
        }
        //接收发送的返回消息并且打印
        //再将这个buffer进行清空
        if(recvfrom(s,buf,BUFLEN,0,(struct sockaddr *)&si_other,&slen)==-1){
             die("recvfrom()");
        }
        puts(buf);
        bzero(&buf,sizeof(buf));

    }
    close(s);
    return 0;
}

warning: this program uses gets(), which is unsafe.

Enter message:send data

send data

Enter message:

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这