1. UDP简介

  UDP 和TCP 的区别包括 1. 面向字节流和面向报文 2. TCP必须要建立连接后才能进行数据交换,但是UDP则并没有连接的建立和释放过程。面向字节流说明,tcp报文段(segment)是没有边界的,当服务器发送多个报文段到客户端时,客户端可能会把着多个报文段合并成一个报文段进行接收。但是对于UDP来说,数据是通过报文段进行传输的。

  如果说TCP协议可以用打电话去比喻,那么UDP协议可以用邮箱来形容。用邮箱传递信息时,虽然有丢失的可能性。但是用户1发送的信件和用户2接受的信件肯定是相同的。

2. 用UDP编写echo server

  使用UDP,我们只需要修改一下socket函数的参数就OK了。

int client_sock = socket(PF_INET, SOCK_DGRAM, );

  然后就是创建两个表示客户端和服务端地址的sockaddr_in结构,其中serv_addr的各个字段需要我们自己填充。但是client_addr的各个字段是通过recvfrom通过指针进行自动填充。

struct sockaddr_in serv_addr, client_addr;

  填充serv_addr的各个字段:

 serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons();

   下来使用bind函数将套接字和服务器地址进行绑定。

 if (bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < ) {
err_exit("bind error");
}

  数据传输方面使用recv族和sendto进行数据传输,这里值得注意的是只有sendto中的sockaddr_in结构是需要手动填充的,sendto中的地址表示要发送的目标地址。recvfrom中的是获取数据的源地址。下图是echo服务器的交互流程。

      

3. 地址长度所遇到的一个坑

   在写echo服务器中遇到一个问题,服务器端在运行过程中总是会出现如下错误:
  在stackoverflow看了下知道了应该是sockaddr的问题。出问题的代码就是下面这一行。问题就在client_addr这块。
int sLen = sendto(serv_sock, buffer, rLen, MSG_CONFIRM,
(struct sockaddr *)&client_addr, recv_addr_len);

  client_addr是通过服务端调用recvfrom获取的,我心想这也不用我手动填啊,怎么就又错了。又反复看了书上的代码,确定地址的获取方式没有错,通过打印我发现地址确实有问题,端口和地址都不对。在网上搜了下 udp echo server的代码,用可以正常运行的代码和我的代码细细比对,终于发现了问题所在。问题就出在地址长度的初始化上,我一直以为recvfrom中的地址长度是值-返回模式,但是实际上这个值也是要在recvfrom中起作用的。如果这个值不正确,client_addr的值也是错误的,导致服务器无法正常的把数据发送到客户端。就酱。。。

socklen_t recv_addr_len = sizeof(client_addr); //正确的初始化方式
//socklen_t recv_addr_len; //错误的初始化方式
int rLen = recvfrom(serv_sock, buffer, MAX_LEN, MSG_WAITALL,
(struct sockaddr *)&client_addr, &recv_addr_len);

4. 参考

[3]  TCP/IP网络编程

 
 
 
 
 
 
 
 

网络编程-UDP echo server的更多相关文章

  1. Socket网络编程-UDP编程

    Socket网络编程-UDP编程 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.UDP编程概述 1>.UDP服务端编程流程 创建socket对象.socket.SOCK_ ...

  2. c/c++ 网络编程 UDP 设定MTU

    网络编程 UDP 设定MTU MTU(Maximun Transmisson Unit):一次送信的最大size. 在程序里动态改变MTU.注意:程序运行需要root权限. 程序运行的方法: sudo ...

  3. c/c++ 网络编程 UDP up/down 网卡

    网络编程 UDP up/down 网卡 在程序里动态改变网卡的状态.注意:程序运行需要root权限. 程序运行的方法: sudo ./a.out 1,关闭网卡 #include <stdio.h ...

  4. c/c++ 网络编程 UDP 改变网关和网卡名字

    网络编程 UDP 改变网关和网卡名字 在程序里动态改变网关和网卡名字 1,改变网卡名字 #include <stdio.h> #include <string.h> #incl ...

  5. c/c++ 网络编程 UDP 改变网卡的硬件地址

    网络编程 UDP 改变网卡的硬件地址 在程序里动态改变网卡的硬件地址 1,取得网卡的硬件地址 #include <stdio.h> #include <string.h> #i ...

  6. c/c++ 网络编程 UDP 改变IP地址

    网络编程 UDP 改变IP地址 在程序里动态改变主机的IP地址 1,改变ipv4的地址 #include <stdio.h> #include <string.h> #incl ...

  7. c/c++ 网络编程 UDP 用if_nameindex和ioctl取得主机网络信息

    网络编程 UDP 用if_nameindex和ioctl取得主机网络信息 getifaddrs函数取得的东西太多了,如果只想取得网卡名字和网卡编号可以用下面的2个函数. 1,if_nameindex ...

  8. c/c++ 网络编程 UDP 主机网络信息取得

    网络编程 UDP 主机网络信息取得 1,if_nametoindex 通过网卡名字取得网卡编号 2,if_indextoname 通过网卡编号取得网卡名字 #include <stdio.h&g ...

  9. c/c++ 网络编程 UDP 发送端 bind 作用

    网络编程 UDP 发送端 bind 作用 upd 发送端 调用bind函数的效果:把socket特定到一个指定的端口,如果不调用bind,内核会随机分配一个端口. upd 发送端 调用bind函数的目 ...

随机推荐

  1. Magazine Delivery(POJ1695)【DP】

    题意:要求用三辆车往n座城市投递货物,起点都在一号城市,每辆车可以载任意数量的货物,投递顺序必须与城市编号递增序一致,并且,每次同时都只能有一辆车在跑路.求最短总路径之和. 思路:每时每刻,能够充分决 ...

  2. 从入门到自闭之Python--Django Rest_Framework

    核心思想: 缩减编写api接口的代码 Django REST framework是一个建立在Django基础之上的Web 应用开发框架,可以快速的开发REST API接口应用.在REST framew ...

  3. log4j rootLogger配置示例(log4j.properties)

    log4j.rootLogger=INFO,commonLogger, log4j.appender.commonLogger=org.apache.log4j.ConsoleAppenderlog4 ...

  4. python项目内import其他内部package的模块的正确方法

    转载 :https://blog.csdn.net/u011089523/article/details/52931844 本文主要介绍如何在一个Python项目中,优雅的实现项目内各个package ...

  5. 牛客 109B 好位置 (字符串水题)

    大意: 给定字符串$s1,s2$, 对于$s1$中所有与$s2$相等的子序列$t$, $t$在$s1$中的下标定义为好位置. 求$s1$是否所有位置都是好位置. 显然$s1$的前缀要与$s2$相等, ...

  6. Neo4j Cypher语法(一)

    目录 Cypher手册详解 1 背景 2 唯一性 3 语法 3.1 命名规则 3.2 表达式 3.3 变量与保留关键字 3.4 参数 3.5 操作符 3.6 模式 3.7 列表 Cypher手册详解 ...

  7. winfrom 点击按钮button弹框显示颜色集

    1.窗体托一个按钮button: 2.单击事件: private void btnForeColor_Click(object sender, EventArgs e) { using (ColorD ...

  8. 初识python之了解其背景和安装

    1.Python的发展 Python语言诞生于1990年,由Guido van Rossum设计并领导开发.1989年12月,Guido考虑启动一个开发项目以打发圣诞节前后的时间,所以决定为当时正在构 ...

  9. CentOS 7.6 64位安装docker并设置开机启动

    步骤如下 安装docker.docker-compose yum -y install docker-io docker-compose 启动docker service docker start 设 ...

  10. Android-分享多图到微信好友

    /** * 微信分享(多图片) */ private static void shareWeChatByImgList(String kDescription, List<File> im ...