recv用TCP和TUDP下的区别
recv是可以用在UDP套接字上的,前提是该套接字调用过bind或者connect,那它用在TCP和UDP套接字上时有什么区别呢?
下面做一个测试,分别使用UDP、TCP实现一对C/S、客户端发送12字节数据,服务器接受的时候用10字节大小的buffer去接受。
TCP
tcpSvr:
/*
* gcc -o tcpSvr ./tcpSvr.c
*/
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <errno.h> const int PORT = ; int main(int argc, char **argv)
{
int fd = socket(AF_INET, SOCK_STREAM, );
if (fd == -)
{
perror("socket");
return errno;
} struct sockaddr_in addr;
memset(&addr, , sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(PORT); if (- == bind(fd, (struct sockaddr*)&addr, sizeof(addr)))
{
perror("bind");
return errno;
} if (- == listen(fd, ))
{
perror("listen");
return errno;
} struct sockaddr_in cli_addr;
socklen_t len = sizeof(cli_addr);
int client = accept(fd, (struct sockaddr*)&cli_addr, &len);
if (client == -)
{
perror("accept");
return errno;
} printf("accept an client\n"); char buf[];
while()
{
memset(buf, , );
int iRet = recv(client, buf, , );
printf("recv data len [%d]\n", iRet);
printf("recv content [%s]\n", buf);
sleep();
}
close(fd); return ;
}
tcpCli:
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <errno.h> const int PORT = ; int main(int argc, char **argv)
{
int fd = socket(AF_INET, SOCK_STREAM, );
if (fd == -)
{
perror("socket");
return errno;
} struct sockaddr_in addr;
memset(&addr, , sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(PORT); if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -)
{
perror("connect");
return errno;
} char buf[] = "hello world!";
while ()
{
int iRet = send(fd, buf, strlen(buf), );
printf("Send data len [%d]\n", iRet);
printf("Send content [%s]\n", buf);
sleep();
}
close(fd); return ;
}
结果:


UDP
udpSvr
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <errno.h> const int PORT = ; int main(int argc, char **argv)
{
int fd = socket(AF_INET, SOCK_DGRAM, );
if (fd == -)
{
perror("socket");
return errno;
} struct sockaddr_in addr;
memset(&addr, , sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(PORT); if (- == bind(fd, (struct sockaddr*)&addr, sizeof(addr)))
{
perror("bind");
return errno;
} char buf[];
while()
{
memset(buf, , );
int iRet = recv(fd, buf, , );
printf("recv data len [%d]\n", iRet);
printf("recv content [%s]\n", buf);
}
close(fd); return ;
}
udpCli:
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <errno.h> const int PORT = ; int main(int argc, char **argv)
{
int fd = socket(AF_INET, SOCK_DGRAM, );
if (fd == -)
{
perror("socket");
return errno;
} struct sockaddr_in addr;
memset(&addr, , sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(PORT); char buf[] = "hello world!";
while ()
{
int iRet = sendto(fd, buf, strlen(buf), , (struct sockaddr*)&addr, sizeof(addr));
printf("Send data len [%d]\n", iRet);
printf("Send content [%s]\n", buf);
break;
}
close(fd); return ;
}
结果:


结论:
当收到的数据大于传入recv的buffer大小时,多余的字节,UDP会丢弃,TCP可以在下次调用recv的时候读取到,这也是为什么说TCP是基于流的协议。
所以当读取UDP数据时一定要注意buffer的大小,应使它大于IP层的数据报大小。
还需要注意的是,发送UDP数据的时候包的大小不应该导致IP分片,否则会造成乱序、丢包。
recv用TCP和TUDP下的区别的更多相关文章
- OSI及TCP/IP的概念和区别
什么是TCP/IP协议 TCP/IP协议(Transfer Controln Protocol/Internet Protocol)叫做传输控制/网际协议,又叫网络通讯协议,这个协议是Internet ...
- 从Docker在Linux和Windows下的区别简单理解Docker的层次结构
上篇文章我们成功在Windows下安装了Docker,输出了一个简单的Hello World程序.本文中我们将利用Docker已有的云端镜像training/webapp来发布一个简单Python的W ...
- TCP协议与HTTP协议区别
一.TCP协议与HTTP协议区别 1.直观认识 TCP协议对应于传输层,而HTTP协议对应于应用层,从本质上来说,二者没有可比性.Http协议是建立在TCP协议基础之上的,当浏览器需要从服务器获取网页 ...
- 盒模型与在低版本IE下的区别
对css有一定了解的同学一定听说过盒模型,在这里以我自己的一点儿了解和认知来解释一下盒模型与盒模型在低版本IE浏览器下与其他浏览器下的区别. W3c标准下的盒模型 盒模型由 content(内容),p ...
- TCP/IP协议原理与应用笔记05:TCP/IP协议下的网关
大家都知道,从一个房间走到另一个房间,必然要经过一扇门.同样,从一个网络向另一个网络发送信息,也必须经过一道“关口”,这道关口就是网关.顾名思义,网关(Gateway)就是一个网络连接到另一个网络的& ...
- socket在windows下和linux下的区别
原文:socket在windows下和linux下的区别 1)头文件 windows下winsock.h/winsock2.h linux下sys/socket.h 错误处理:errno.h 2 ...
- 第12讲 | TCP协议(下):西行必定多妖孽,恒心智慧消磨难
第12讲 | TCP协议(下):西行必定多妖孽,恒心智慧消磨难 如何做个靠谱的人? 有问有答,任务发送和接收有记录,完成有反馈. 如何实现一个靠谱的协议? TCP 协议使用的也是同样的模式.为了保证顺 ...
- linux下recv 、send阻塞、非阻塞区别和用法
非阻塞IO 和阻塞IO: 在网络编程中对于一个网络句柄会遇到阻塞IO 和非阻塞IO 的概念, 这里对于这两种socket 先做一下说明: 基本概念: 阻塞IO:: socket 的阻塞模式 ...
- TCP和UDP的具体区别
TCP和UDP的最完整的区别 TCP UDP TCP与UDP基本区别: 1.基于连接与无连接 2.TCP要求系统资源较多,UDP较少: 3.UDP程序结构较简单 4.流模式(TCP)与数据报模式(UD ...
随机推荐
- java 取模运算% 实则取余 简述 例子 应用在数据库分库分表
java 取模运算% 实则取余 简述 例子 应用在数据库分库分表 取模运算 求模运算与求余运算不同.“模”是“Mod”的音译,模运算多应用于程序编写中. Mod的含义为求余.模运算在数论和程序设计中 ...
- Java使用Itext5.5.10进行pdf签章
说到PDF数字签名签章,这个其实也是数字证书信息安全的应用范畴,关于数字证书和数字签名,网上有很多解释说明,但讲解都多不够详细准确,这边推荐一篇大神的博文,讲解浅显易懂形象数字证书 数字签名 数据加密 ...
- 【jsp】JSP中page指令isThreadSafe
<%@ page isThreadSafe="true|false" %> 默认值为true isThreadSafe=false模式表示它是以Singleton模式运 ...
- 代码管理(三)sourcetree 的使用
一.SourceTree简介 SourceTree 是 Windows 和Mac OS X 下免费的 Git 和 Hg 客户端,拥有可视化界面,容易上手操作.同时它也是Mercurial和Subv ...
- C#程序证书创建工具 (Makecert.exe)
原文地址:https://msdn.microsoft.com/zh-cn/library/bfsktky3(VS.80).aspx 证书创建工具生成仅用于测试目的的 X.509 证书.它创建用于数字 ...
- NET MVC全局异常处理(一) 【转载】网站遭遇DDoS攻击怎么办 使用 HttpRequester 更方便的发起 HTTP 请求 C#文件流。 Url的Base64编码以及解码 C#计算字符串长度,汉字算两个字符 2019周笔记(2.18-2.23) Mysql语句中当前时间不能直接使用C#中的Date.Now传输 Mysql中Count函数的正确使用
NET MVC全局异常处理(一) 目录 .NET MVC全局异常处理 IIS配置 静态错误页配置 .NET错误页配置 程序设置 全局异常配置 .NET MVC全局异常处理 一直知道有.NET有相关 ...
- 使用 Cookie 而无需 ASP.NET 核心标识的身份验证
https://docs.microsoft.com/zh-cn/aspnet/core/security/authentication/cookie?tabs=aspnetcore2x#tabpan ...
- ekho安装及测试(中文文字转语音)
1. 官网下载源码包 地址:http://www.eguidedog.net/ekho.php 2. 安装 xz -d ekho-7.5.tar.xz tar -xvf ekho-7.5.tar ap ...
- Mysql命令行改动字段类型
在做微信公众平台 知识百科(账号:zhishiwiki) 时,由于字段先前设计的不合理.导致内容装不下,因此须要改动其字段类型为 text 这里使用到了 alter 命令 alter table 表名 ...
- java File类中的mkdir()和mkdirs()有什么区别
mkdir() 只能在已经存在的目录中创建创建文件夹. mkdirs() 可以在不存在的目录中创建文件夹.诸如:a\\b,既可以创建多级目录.