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. yii2框架(一)安装

    手动安装下载yii2basic出现以下错误 2 修改 G:\learn\yii-basic-app-2.0.11\basic\config下web.conf 为cookieValidationKey设 ...

  2. Notepad++插件安装和使用和打开大文件

    版权声明:本文为博主皮皮http://blog.csdn.net/pipisorry原创文章,未经博主同意不得转载. https://blog.csdn.net/pipisorry/article/d ...

  3. Flask系列之源码分析(二)

    应用技术点 python之__setattr__ python之threading.local python之偏函数 flask源码上下文管理 1.综述过程 将请求对象压入栈 1.请求进入 __cal ...

  4. Android初体验之Monkey和MonkeyRunner

    原文地址https://blog.csdn.net/mad1989/article/details/38087737 Monkey 什么是Monkey Monkey是Android中的一个命令行工具, ...

  5. cocos进阶教程(5)各种动画使用心得

    Node类 不解释 ActionTimeline类是一个3.0时代的动画类, 案例一 //建立node方案一Data data = FileUtils::getInstance()->getDa ...

  6. KEYENCE Programming Contest 2019 Solution

    A - Beginning 签到. #include <bits/stdc++.h> using namespace std; int main() { ]; while (scanf(& ...

  7. CF337C - Quiz

    /*题目大意,给出n道题,假设答对了m道题,求最小的分数,有一个规则,就是连续答对num==k道题那么分数就翻倍,然后num清零,从新开始计数,到大连续k道的时候 要先加上这道题的分数1,再乘以2, ...

  8. Vue学习笔记之vue-cli脚手架安装和webpack-simple模板项目生成

    vue-cli 是一个官方发布 vue.js 项目脚手架,使用 vue-cli 可以快速创建 vue 项目. GitHub地址是:https://github.com/vuejs/vue-cli 一. ...

  9. P1270 “访问”美术馆(树形dp)

    P1270 “访问”美术馆 艺术馆最多有100个展室 ------> 节点数$<=100*2<2^{8}=256$ 所以可以开一个$f[i][j]$表示到第$i$个点为止花去$j$分 ...

  10. 20155201 2016-2017-2 《Java程序设计》第八周学习总结

    20155201 2016-2017-2 <Java程序设计>第八周学习总结 教材学习内容总结 第十四章 NIO与NIO2 相对于串流输入/输出使用InputSteam,OutputStr ...