body, table{font-family: 微软雅黑; font-size: 10pt}
table{border-collapse: collapse; border: solid gray; border-width: 2px 0 2px 0;}
th{border: 1px solid gray; padding: 4px; background-color: #DDD;}
td{border: 1px solid gray; padding: 4px;}
tr:nth-child(2n){background-color: #f8f8f8;}

1.1. 使用UDP协议的流程图

UDP通信流程图如下:

服务端:socket---bind---recvfrom---sendto---close

客户端:socket----------sendto---recvfrom---close

//客户端发数据,系统会自动分配一个端口号,这个端口在你使用的这段时间不会关闭,除非自己close
sendto()
函数原型:
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
该函数比 send() 函数多了两个参数,
to 表示目地机的IP地址和端口号信息;
tolen 常常被赋值为sizeof (struct sockaddr)。
sendto() 函数也返回实际发送的数据字节长度或在出现发送错误时返回-1。
recvfrom()
函数原型:
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);
from 是一个 struct sockaddr 类型的变量,该变量保存连接机的IP地址及端口号。
fromlen 常置为sizeof (struct sockaddr)。
//如果不想获取发送方的信息,可以最后两项直接写NULL
recvfrom() 返回时,fromlen包含实际存入from中的数据字节数。recvfrom()函数返回接收到的字节数或当出现错误时返回-1,并置相应的errno。
udp_server.c udp_client.c
#include "func.h"
int main(int argc,char** argv)
{
        if(argc!=3)
        {
                printf("error args\n");
                return -1;
        }
        int sfd=socket(AF_INET,SOCK_DGRAM,0);
        if(-1==sfd)
        {
                perror("socket");
                return -1;
        }       
        printf("sfd=%d\n",sfd);
        struct sockaddr_in ser;
        memset(&ser,0,sizeof(ser));
        ser.sin_family=AF_INET;
        ser.sin_port=htons(atoi(argv[2])); 
        ser.sin_addr.s_addr=inet_addr(argv[1]);
        int ret;
        ret=bind(sfd,(struct sockaddr*)&ser,sizeof(struct sockaddr));
        if(-1==ret)
        {
                perror("bind");
                return -1;
        }
        struct sockaddr_in client;
        memset(&client,0,sizeof(client));
        int addrlen=sizeof(client);
        char buf[128]={0};
        ret=recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&client,&addrlen);
//阻塞函数,会卡在这里,直到读到客户端,拿到客户端IP和端口;
        if(-1==ret)
        {
                perror("recvfrom");
                return -1;
        }
        printf("client ip =%s,port =%d\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
        printf("recv buf =%s\n",buf);
        ret=sendto(sfd,"I am server",11,0,(struct sockaddr*)&client,sizeof(struct sockaddr));
        if(-1==ret)
        {
                perror("sendto");
                return -1;
        }
        close(sfd);
        return 0;
}
#include "func.h"
int main(int argc,char** argv)
{
        if(argc!=3)
        {
                printf("error args\n");
                return -1;
        }
        int sfd=socket(AF_INET,SOCK_DGRAM,0);
        if(-1==sfd)
        {
                perror("socket");
                return -1;
        }       
        printf("sfd=%d\n",sfd);
        struct sockaddr_in ser;
        memset(&ser,0,sizeof(ser));
        ser.sin_family=AF_INET;
        ser.sin_port=htons(atoi(argv[2]));
        ser.sin_addr.s_addr=inet_addr(argv[1]);
        int ret;
        ret=sendto(sfd,"I am client",11,0,(struct sockaddr*)&ser,sizeof(struct sockaddr));
        if(-1==ret)
        {
                perror("sendto");
                return -1;
        }
        struct sockaddr_in client;
        memset(&client,0,sizeof(client));
        int addrlen=sizeof(client);
        char buf[128]={0};
        ret=recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&client,&addrlen);
//不想获取发送方发过来的数据就直接最后两个参数写NULL
        if(-1==ret)
        {
                perror("recvfrom");
                return -1;
        }
        printf("server ip =%s,port =%d\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
        printf("recv buf =%s\n",buf);
        close(sfd);
        return 0;
}
func.h
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

                                          
注意:操作系统的UDP接收流程如下:收到一个UDP包后,验证没有错误后,放入一个包队列中,队列中的每一个元素就是一个完整的UDP包。当应用程序通过recvfrom()读取时,OS把相应的一个完整UDP包取出,然后拷贝到用户提供的内存中,物理用户提供的内存大小是多少,OS都会完整取出一个UDP包。如果用户提供的内存小于这个UDP包的大小,那么在填充满内存后,UDP包剩余的部分就会被丢弃,以后再也无法取回。
这与TCP接收完全不同,TCP没有完整包的概念,也没有边界,OS只会取出用户要求的大小,剩余的仍然保留在OS中,下次还可以继续取出。

(UDP)socket编程的更多相关文章

  1. tcp/udp socket编程异同

    一.TCP与UDP的区别 基于连接与无连接 对系统资源的要求(TCP较多,UDP少) UDP程序结构较简单 流模式与数据报模式 TCP保证数据正确性,UDP可能丢包 TCP保证数据顺序,UDP不保证 ...

  2. Linux网络编程:UDP Socket编程范例

    TCP协议提供的是一种可靠的,复杂的,面向连接的数据流(SOCK_STREAM)传输服务,它通过三段式握手过程建立连接.TCP有一种"重传确认"机制,即接收端收到数据后要发出一个肯 ...

  3. Go语言TCP/UDP Socket编程

    1. TCP编程 TCPClient // TCPClient project main.go package main import ( "fmt" "net" ...

  4. tcp udp socket编程

    http://blog.csdn.net/ns_code/article/details/14128987

  5. iOS Socket编程-C语言版(UDP)

    . UDP Socket编程 先讲一讲UDP编程,因为比TCP要简单多了.首先,我们需要明白UDP是用户数据报协议,英文名为User Datagram Protocol,它是面向无连接的. 注意:So ...

  6. Java Socket编程题库

    一.    填空题 ___ IP地址____用来标志网络中的一个通信实体的地址.通信实体可以是计算机,路由器等. 统一资源定位符URL是指向互联网"资源"的指针,由4部分组成:协议 ...

  7. 如何为可扩展系统进行Java Socket编程

    从简单I/O到异步非阻塞channel的Java Socket模型演变之旅 上世纪九十年代后期,我在一家在线视频游戏工资工作,在哪里我主要的工作就是编写Unix Unix Berkley Socket ...

  8. Linux编程之UDP SOCKET全攻略

    这篇文章将对linux下udp socket编程重要知识点进行总结,无论是开发人员应知应会的,还是说udp socket的一些偏僻知识点,本文都会讲到.尽可能做到,读了一篇文章之后,大家对udp so ...

  9. 8.1 Socket编程

    8.1 Socket编程 在很多底层网络应用开发者的眼里一切编程都是Socket,话虽然有点夸张,但却也几乎如此了,现在的网络编程几乎都是用Socket来编程.你想过这些情景么?我们每天打开浏览器浏览 ...

  10. 【转】Linux编程之UDP SOCKET全攻略

    转自:http://www.cnblogs.com/skyfsm/p/6287787.html?utm_source=itdadao&utm_medium=referral 这篇文章将对lin ...

随机推荐

  1. JavaScript如何把字符串中每个单词首字母转化为大写

    先上代码,再做解释. 思路分析: 1. 首先先把字符串中的单词转化为小写(toLowerCase),再对其进行截取(split),截取依据为按照空格截取: 2. 此时经过步骤一之后得到的东西是一个数组 ...

  2. Spark SQL的整体实现逻辑

    1.sql语句的模块解析 当我们写一个查询语句时,一般包含三个部分,select部分,from数据源部分,where限制条件部分,这三部分的内容在sql中有专门的名称: 当我们写sql时,如上图所示, ...

  3. 单机部署PXC

    在一台机器上安装PXC Linux:centos 7     IP:192.168.30.221 PXC版本:Percona-XtraDB-Cluster-5.7.17-rel13-29.20.3.L ...

  4. mysql++使用

    Mysql++是官方发布的.一个为MySQL设计的C++语言的API.Mysql++为Mysql的C-Api的再次封装,它用STL(Standard Template Language)开发并编写,并 ...

  5. malloc calloc realloc 区别

    (1)C语言跟内存分配方式 <1>从静态存储区域分配.       内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量.static变量.<2> ...

  6. UI自动化测试框架之Selenium关键字驱动

    一.原理及特点 1. 关键字驱动测试是数据驱动测试的一种改进类型 2. 主要关键字包括三类:被操作对象(Item).操作(Operation)和值(value),用面向对象形式可将其表现为Item.O ...

  7. bzoj1609 / P2896 [USACO08FEB]一起吃饭Eating Together(最长不降子序列)

    P2896 [USACO08FEB]一起吃饭Eating Together 显然的最长不升/降子序列,求出最长值,则答案为$n-$最长值(改掉剩下的). 复杂度$O(nlogn)$ (然鹅有神仙写了$ ...

  8. object类之toString方法

    object是所有类的基类 如果没有使用extends关键字指明其基类,则默认基类为object类 public class Person{ ........ } 等价于: public class ...

  9. Rabbitmq安装、集群与高可用配置

    历史: RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现.AMQP 的出现其实也是应了广大人民群众的需求,虽然在同步消息通讯的世界里有很多 ...

  10. 20145339顿珠达杰 《网络对抗技术》 逆向与Bof基础

    目的 通过一些方法,使能够运行本不该被运行的代码部分,或得到shell的使用: 将正常运行代码部分某处call后的目标地址,修改为另一部分我们希望执行.却本不应该执行的代码部分首地址(这需要我们有一定 ...