UDP通讯方式

简介

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

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

1#include <netinet/in.h> 2struct sockaddr_in { 3 short sin_family; // e.g. AF_INET 4 unsigned short sin_port; // e.g. htons(3490) 5 struct in_addr sin_addr; // see struct in_addr, below 6 char sin_zero[8]; // zero this if you want to 7}; 8struct in_addr { 9 unsigned long s_addr; // load with inet_aton() 10};
  • 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()

1#include <stdio.h> 2#include <string.h> 3#include <stdlib.h> 4#include <arpa/inet.h> 5#include <sys/socket.h> 6#define BUFLEN 512//最大的缓冲长度 7#define PORT 8888//监听数据的端口 8void die(char *s){ 9 perror(s); 10 exit(1); 11} 12int main(int argc, char const* argv[]) 13{ 14 struct sockaddr_in si_me,si_other; 15 int s,i,slen=sizeof(si_other),recv_len; 16 char buf[BUFLEN]; 17 //创建一个UDP的socket 18 if((s=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))==-1){ 19 die("socket"); 20 } 21 //将这个结构清零 22 memset((char *)&si_me,0,sizeof(si_me)); 23 24 si_me.sin_family=AF_INET; 25 si_me.sin_port=htons(PORT); 26 si_me.sin_addr.s_addr=htonl(INADDR_ANY); 27 //指定需要绑定的端口 28 if(bind(s,(struct sockaddr*)&si_me,sizeof(si_me))==-1){ 29 die("bind"); 30 } 31 while(1){ 32 printf("Waiting for data..."); 33 fflush(stdout); 34 //从远程接收数据,这是一个堵塞的函数,直到接触到数据为止 35 if((recv_len=recvfrom(s,buf,BUFLEN,0,(struct sockaddr*)&si_other,&slen))==-1) 36 { 37 die("recvfrom()"); 38 } 39 //打印客户端的信息及其相关的信息 40 printf("Received packet from %s:%d\n",inet_ntoa(si_other.sin_addr),ntohs(si_other.sin_port)); 41 printf("recv Data:%s\n",buf); 42 //将接收到的数据进行发送 43 if(sendto(s,buf,recv_len,0,(struct sockaddr*)&si_other,slen)==-1){ 44 die("sendto()"); 45 } 46 //重置所有的数据 47 bzero(&buf,sizeof(buf)); 48 } 49 close(s);//关闭socket 50 return 0; 51} 52

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

recv Data:send data

client端

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

1#include <stdio.h> 2#include <string.h> 3#include <stdlib.h> 4#include <arpa/inet.h> 5#include <sys/socket.h> 6#define SERVER "127.0.0.1" 7#define BUFLEN 512//缓冲区的大小 8#define PORT 8888//发送数据的端口 9void die(char *s){ 10 perror(s); 11 exit(1); 12} 13int main(int argc, char const* argv[]) 14{ 15 struct sockaddr_in si_other; 16 int s,i,slen=sizeof(si_other); 17 char buf[BUFLEN]; 18 char message[BUFLEN]; 19 if((s=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))==-1) 20 { 21 die("socket"); 22 } 23 memset((char *)&si_other,0,sizeof(si_other)); 24 si_other.sin_family=AF_INET; 25 si_other.sin_port=htons(PORT); 26 27 if(inet_aton(SERVER,&si_other.sin_addr)==0){ 28 fprintf(stderr,"inet_atom() failed\n"); 29 exit(1); 30 } 31 while(1){ 32 printf("Enter message:"); 33 gets(message); 34 //发送数据 35 if(sendto(s,message,strlen(message),0,(struct sockaddr *)&si_other,slen)==-1){ 36 die("sendto()"); 37 } 38 //接收发送的返回消息并且打印 39 //再将这个buffer进行清空 40 if(recvfrom(s,buf,BUFLEN,0,(struct sockaddr *)&si_other,&slen)==-1){ 41 die("recvfrom()"); 42 } 43 puts(buf); 44 bzero(&buf,sizeof(buf)); 45 46 } 47 close(s); 48 return 0; 49} 50

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

Enter message:send data

send data

Enter message:

点赞
收藏

评论区

加载中...

相关推荐

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

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

UDP通讯方式 - HelloWorld