TCP/IP网络编程 第十五章:套接字和标准I/O

标准I/O函数的优点

标准I/O函数的两个优点


将标准I/O函数用于数据通信并非难事。但仅掌握函数使用方法并没有太大意义,至少应该
了解这些函数具有的优点。下面列出的是标准I/O函数的两大优点:
□标准I/O函数具有良好的移植性(Portability)
□标准I/O函数可以利用缓冲提高性能。
关于移植性无需过多解释。不仅是IO函数,所有标准函数具有良好的移植性。因为,为了支持所有操作系统(编译器),这些函数都是按照ANSI C标准定义的。当然,这并不局限于网络编程,而是适用于所有编程领域。
接下来讨论标准I/O函数的第二个优点。使用标准IO函数时会得到额外的缓冲支持。这种表达方式也许会带来一些混乱,因为之前讲过,创建套接字时操作系统会准备I/O缓冲。造成更大混乱之前,先说明这两种缓冲之间的关系。创建套接字时,操作系统将生成用于I/O的缓冲。此缓冲在执行TCP协议时发挥着非常重要的作用。此时若使用标准IO函数,将得到额外的另一缓冲的支持。大概意思如下图所示:

 从图中可以看到,使用标准I/O函数传输数据时,经过两个缓冲。例如,通过fputs函数传输字符串“Hello”时,首先将数据传递到标准IO函数的缓冲。然后数据将移动到套接字输出缓冲,最后将字符串发送到对方主机。
既然知道了两个缓冲的关系,接下来再说明各自的用途。设置缓冲的主要目的是为了提高性能,但套接字中的缓冲主要是为了实现TCP协议而设立的。例如,TCP传输中丢失数据时将再次传递
,而再次发送数据则意味着在某地保存了数据。存在什么地方呢?套接字的输出缓冲。与之
相反,使用标准IO函数缓冲的主要目的是为提高性能,但是实际上,缓冲并非在所有情况下都能带来卓越的性能。但需要传输的数据越多,有无缓冲带来的性能差异越大。可以通过如下两种角度说明性能的提高。
□传输的数据量
□数据向输出缓冲移动的次数
比较1个字节的数据发送10次(10个数据包)的情况和累计10个字节发送1次的情况。发送数据时使用的数据包中含有头信息(首部)。头信息与数据大小无关,是按照一定的格式填入的。即使假设该头信息占用40个字节(实际更大),需要传递的数据量也存在较大差别。
□1个字节10次40×10=400字节
□10个字节1次40x1=40字节
另外,为了发送数据,向套接字输出缓冲移动数据也会消耗不少时间。但这同样与移动次数
有关。1个字节数据共移动10次花费的时间将近10个字节数据移动1次花费时间的10倍。

标准I/O函数的几个缺点


如果就此结束说明,各位可能认为标准I/O函数只有优点。其实它同样有缺点,整理如下。
□不容易进行双向通信。
□有时可能频繁调用fflush函数。(用以刷新缓冲区)
□需要以FILE结构体指针的形式返回文件描述符。
假设各位已掌握了C语言中的绝大部分文件IO相关知识。打开文件时,如果希望同时进行读写操作,则应以r+、w+、a+模式打开。但因为缓冲的缘故,每次切换读写工作状态时应调用fflush函数。这也会影响基于缓冲的性能提高。而且,为了使用标准IO函数,需要FILE结构体指针(以下简称“FILE指针”)。而创建套接字时默认返回文件描述符,因此需要将文件描述符转化为FILE指针。

使用标准I/O函数


如前所述,创建套接字时返回文件描述符,而为了使用标准IO函数,只能将其转换为FILE
结构体指针。先介绍其转换方法。


利用fdopen函数转换为FILE结构体指针


可以通过fdopen函数将创建套接字时返回的文件描述符转换为标准IO函数中使用的FILE结
构体指针。

#include<stdio.h>
FILE * fdopen(int fildes, const char * mode);
//成功时返回转换的FILE结构体指针,失败时返回NULL。fildes     //需要转换的文件描述符。mode       //将要创建的FILE结构体指针的模式(mode)信息。

上述函数的第二个参数与fopen函数中的打开模式相同。常用的参数有读模式"r"和写模式"w"。

利用fileno函数转化为文件描述符

接下来介绍与fdopen函数提供功能相反的函数,该函数在有些情况下非常好用。

#include<stdio.h>
int fileno(FILE * stream);//成功时返回转化后的文件描述符,失败时返回-1

此函数的用法也非常简单,向该函数传递FILE指针参数时返回相应文件描述符。

基于套接字的标准I/O函数使用
 

前面介绍了标准IO函数的优缺点,同时介绍了文件描述符转换为FILE指针的方法。下面将其适用于套接字。虽然是套接字操作,但并没有需要另外说明的内容,只需简单应用这些函数。接下来将之前的回声服务器端和客户端改为基于标准IO函数的数据交换形式。
无论是服务器端还是客户喘,更改方式并无差异。只需调用fdopen函数并使用标准IO函数,
相信各位也能自行更改。首先给出更改后的服务器端代码。

#include<"头文件声明和之前章节中的回声服务端相同,故省略">
#define BUF_SIZE 30
void error_handling(char *message);int main(int argc,char *argv[]){int serv_sock,clnt_sock;char message[BUF_SIZE];int str_len,i;struct sockaddr_in serv_addr;struct sockaddr_in clnt_addr;socklen_t clnt_addr_sz;FILE * readfp;FILE * writefp;if(argc!=2){printf("Usage : %s <port>\n",argv[0]);exit(1);}serv_sock=socket(PF_INET,SOCK_STREAM,0);if(serv_sock==-1)error_handling("socket() error");memset(&serv_addr,0,sizeof(serv_addr));serv_addr.sin_family=AF_INET;serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);serv_addr.sin_port=htons(atoi(argv[1]));if(bind(serv_sock,(struct sockaddr*)&serv_addr,sizeof(serv_addr))==-1)error_handling("bind() error");if(listen(serv_sock,5)==-1)error_handling("listen() error");clnt_addr_sz=sizeof(clnt_sock);for(int i=0;i<5;++i){clnt_sock=accept(serv_sock,(struct sockaddr*)&clnt_sock,&clnt_addr_sz);if(clnt_sock==-1)error_handling("accept() error");else printf("Connected client %d \n",i+1);readfp=fdopen(clnt_sock,"r");writefp=fdopen(clnt_sock,"w");while(!feof(readfp)){fgets(message,BUF_SIZE,readfp);   fputs(message,writefp);fflush(writefp);}fclose(readfp);fclose(writefp);}close(serv_sock);return 0;
}void error_handling(char*message){//与之前章节的错误处理函数相同,故省略
}

接下来给出回声客户端代码

#include<"与之前章节的头文件声明相同,故省略">
#define BUF_SIZE 1024
void error_handling(char *message);int main(int argc,char *argv[]){int sock;char message[BUF_SIZE];int str_len;struct sockaddr_int serv_addr;FILE * readfp;FILE * writefp;if(argc!=3){printf("Usage : %s <IP> <port>\n",argv[0]);exit(1);}sock=socket(PF_INET,SOCK_STREAM,0);if(sock==-1)error_handling("socket() error");memset(&serv_addr,0,sizeof(serv_addr));serv_addr.sin_family=AF_INET;serv_addr.sin_addr.s_addr=inet_addr(argv[1]);serv_addr.sin_port=htons(atoi(argv[2]));if(connect(sock,(struct sockaddr*)&serv_addr,sizeof(serv_addr))==-1)error_handling("connect() error");elseputs("Connected.......");readfp=fdopen(sock,"r");writefp=fdopen(sock,"w");while(1){fputs("Input message(Q to quite):",stdout);fgets(message,BUF_SIZE,stdin);if(!strcmp(message,"q\n")||!strcmp(message,"Q\n"))break;fputs(message,writefp);fflush(writefp);fgets(message,BUF_SIZE,readfp);printf("Message from server: %s",message);}fclose(writefp);fclose(readfp);return 0;
}void error_handling(char *message){//和前面章节的错误处理函数相同,故省略。
}

以上就是标准IO函数在套接字编程中的应用方法,因为需要编写额外的代码,所以并不像想象中那么常用。但某些情况下也是非常有用的,而且可以再次复习标准IO函数,对大家也非常有益。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1236.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【AI底层逻辑】——篇章3(下):信息交换信息加密解密信息中的噪声

续&#xff1a;【AI底层逻辑】——篇章3&#xff08;上&#xff09;&#xff1a;数据、信息与知识&香农信息论&信息熵 目录 三、信息是如何交换的 1、互联网与信息交换 2、哈夫曼和有效编码 四、信息的加密与解密 1、密码学的发展 2、可以被公开的密钥 五、信息…

python selenium.webdriver 爬取政策文件

文章目录 获取文章链接批量爬取政策文件应用selenium爬取文件信息数据处理导出为excel 获取文章链接 获取中央人民政府网站链接&#xff0c;进入国务院政策文件库&#xff0c;分为国务院文件和部门文件&#xff08;发改委、工信部、交通运输部、市场监督局、商务部等&#xff…

2023网络安全常见面试题汇总(附答案解析+配套资料)

以下为网络安全各个方向涉及的面试题&#xff0c;星数越多代表问题出现的几率越大&#xff0c;祝各位都能找到满意的工作。 注&#xff1a;所有的资料都整理成了PDF&#xff0c;面试题和答案将会持续更新&#xff0c;因为无论如何也不可能覆盖所有的面试题。 目录 一、渗透测试…

【Python】PyCharm中调用另一个文件的函数或类

&#x1f389;欢迎来到Python专栏~PyCharm中调用另一个文件的函数或类 ☆* o(≧▽≦)o *☆嗨~我是小夏与酒&#x1f379; ✨博客主页&#xff1a;小夏与酒的博客 &#x1f388;该系列文章专栏&#xff1a;Python学习专栏 文章作者技术和水平有限&#xff0c;如果文中出现错误&…

数据分析案例-数据分析师岗位招聘信息可视化

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

LLM - Hugging Face 工程 BERT base model (uncased) 配置

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://blog.csdn.net/caroline_wendy/article/details/131400428 BERT是一个在大量英文数据上以自监督的方式预训练的变换器模型。这意味着它只是在原始文本上进行预训练&#xff0c;没有人以…

MySQL:聚合函数(全面详解)

聚合函数 前言一、聚合函数介绍1、AVG和SUM函数2、 MIN和MAX函数3、COUNT函数 二、GROUP BY1、基本使用2、使用多个列分组3、 GROUP BY中使用WITH ROLLUP 三、HAVING1、基本使用2、WHERE和HAVING的对比 四、 SELECT的执行过程1、查询的结构2、SELECT执行顺序3、SQL 的执行原理 …

积分图像、图像分割、Harris角点检测

目录 1、积分图像 2、图像分割--漫水填充 3、图像分割--分水岭法 4、Harris角点检测 1、积分图像 #include <iostream> #include <opencv2/opencv.hpp>using namespace cv; using namespace std;//积分图像 int test() {//创建一个1616全为1的矩阵,因为2561616M…

分类预测 | MATLAB实现基于Attention-GRU的数据多特征分类预测(门控循环单元融合注意力机制分类预测,含混淆矩阵图、分类图)

分类预测 | MATLAB实现基于Attention-GRU的数据多特征分类预测(门控循环单元融合注意力机制分类预测&#xff0c;含混淆矩阵图、分类图) 目录 分类预测 | MATLAB实现基于Attention-GRU的数据多特征分类预测(门控循环单元融合注意力机制分类预测&#xff0c;含混淆矩阵图、分类图…

Antd List组件增加gutter属性后出现横向滚动,如何解决

第一次使用ant design的List列表组件&#xff0c;设置gutter间隔属性后&#xff0c;页面出现了横向滚动条&#xff0c;查阅文档发现是由于加间隔后导致容器宽度被撑开&#xff0c;ant design官方默认给外层容器加了margin-left和margin-right 解决方法是在外层容器预留一定的pa…

用宏定义完成整数的二进制位的奇偶位互换

代码如下&#xff1a; #include <stdio.h> #define SWAP(num) (((num & 0xAAAAAAAA) >> 1) | ((num & 0x55555555) << 1))int main() {int num 1010;printf("%d\n", num);printf("%d\n", SWAP(num));return 0; }思路如下&…

MySQL数据备份与还原、索引、视图

一.备份与还原 /***************************样例表***************************/ CREATE DATABASE booksDB; use booksDB; CREATE TABLE books ( bk_id INT NOT NULL PRIMARY KEY, bk_title VARCHAR(50) NOT NULL, copyright YEAR NOT NULL …

统计页面左右+上下自适应布局

1:如果需要调整分栏数量,那么只需要删除对应数据,修改百分比即可. <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><style type"text/css" lang"less" >body{margin: 0px ;}.box…

微信小程序用户登录及头像昵称设置教程(前后端)

目录 1.背景分析 2.具体需求分析 3.前端设计 3.1 用户登录 3.2 头像昵称填写&#xff08;个人信息界面&#xff09; 4.后端设计 4.1项目架构分析 4.2 代码分析 实体类 dao层 service层 controller层 工具类 5.nginx部署 6.效果演示 1.背景分析 众所周知&#x…

论文解读|VoxelNet:基于点云的3D物体检测的端到端学习

原创 | 文 BFT机器人 01 摘要 论文提出了表述了一个新的基于点云的3D检测方法&#xff0c;名为VoxelNet&#xff0c;该方法是一个端到端可训练的深度学习架构&#xff0c;利用了稀疏点云的结构特性&#xff0c;直接在稀疏的3D点上进行操作&#xff0c;并通过高效的并行处理体素…

01 - 如何制定性能调优标准?

1、为什么要做性能调优&#xff1f; 一款线上产品如果没有经过性能测试&#xff0c;那它就好比是一颗定时炸弹&#xff0c;你不知道它什么时候会出现问题&#xff0c;你也不清楚它能承受的极限在哪儿。 有些性能问题是时间累积慢慢产生的&#xff0c;到了一定时间自然就爆炸了…

Linux —— 进程状态

目录 一&#xff0c;进程状态分类 二&#xff0c;僵尸进程 三&#xff0c;孤儿进程 一&#xff0c;进程状态分类 进程状态反应进程执行过程中的变化&#xff0c;状态会随外界条件的变化而转换&#xff1b; 三态模型&#xff0c;运行态、就绪态、阻塞态&#xff1b;五态模型…

SpringCloud微服务(三)RabbitMQ、SpringAMQP、elasticsearch、DSL、MQ、ES详细介绍

目录 一、初始MQ 同步调用 异步调用 什么是MQ 执行下面的命令来运行MQ容器&#xff1a; 如果冲突了&#xff0c;可以先查询 RabbitMQ概述 常见消息模型 HelloWorld案例 二、SpringAMQP 引入依赖 Work Queue 消费预取限制 ​编辑 发布、订阅 发布订阅Fanout Ex…

进阶C语言——字符串和内存函数

今天我们学点库函数 字符函数和字符串函数 求字符串长度函数->strlen strlen需要的头文件是string.h ,那它的作用是什么呢&#xff1f;&#xff1f; 他是来求字符串长度的&#xff0c;统计的是’\0’前的字符串长度 #include<stdio.h> #include<string.h> int …

紫光展锐CEO任奇伟博士:用芯赋能,共建XR新生态

7月6日&#xff0c;2023世界人工智能大会在上海世博中心及世博展览馆盛大开幕。紫光集团高级副总裁、紫光展锐CEO任奇伟博士受邀出席芯片主题论坛&#xff0c;并发表题为《用芯赋能&#xff0c;共建XR新生态》的演讲。 世界人工智能大会自2018年创办以来已成功举办五届&#xf…