《TCP/IP网络编程》(第十五章)套接字和标准I/O

之前数据通信时,使用的是read&write函数以及其他各种I/O函数,本章将使用标准I/O函数,例如C语言的fopen、fgetc、fputs等等;C++语言的cout、cin等等

1.使用标准I/O函数的优点

  • ①跨平台兼容性: 标准I/O函数通常是跨平台的,这意味着使用这些函数编写的代码可以在不同的操作系统上编译和运行,而无需修改。
  • ②利用缓冲提高性能: 标准I/O库通常实现了缓冲机制,这意味着数据在实际写入或读取之前会被暂存,这可以提高I/O操作的效率。从下图可以发现,使用标准I/O函数时,会经过两个缓冲,
    例如可以当缓冲区积累了一定量的数据后,再一次性发送,这样可以减少网络通信的次数,提高数据传输的效率。

在这里插入图片描述

2.使用标准I/O函数的缺点

①不能进行双向通信
②有时可能频繁调用fflush函数: fflush()是C语言标准库中的一个函数,用于控制输出流的缓冲,fflush() 强制清空输出流的缓冲区,将缓冲区内的数据发送出去。

int fflush(FILE *stream);//stream 参数是一个指向 FILE 结构的指针

③需要以FILE结构体指针的形式返回文件描述符

3.使用标准I/O函数

3.1 利用fdopen()函数转化为FILE结构体指针

fdopen()用于将一个现有的文件描述符与一个流(stream)关联起来。它允许你使用标准I/O函数(如 fread、fwrite、fscanf、fprintf 等)来操作文件描述符。

FILE *fdopen(
int fd,//文件描述符
const char *mode//指定了流的打开模式
);


/*
常见的模式有:
"r":只读模式。
"w":只写模式,会覆盖文件内容。
"a":追加模式,写入数据到文件末尾。
"r+":读写模式,文件指针放在文件开头。
"w+":读写模式,会覆盖文件内容。
"a+":读写模式,写入数据到文件末尾,但可以读取整个文件。
*/

3.2 利用fileno()函数转换为文件描述符

fileno()用于获取与 FILE 流相关联的文件描述符

int fileno(FILE *stream);//stream 参数是一个指向 FILE 结构的指针

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

这里是基于《TCP/IP网络编程》(第四章)基于TCP的服务器端/客户端(1)中的回声客户端进行的修改,把read&write替换为了标准I/O函数

4.1 示例代码

①服务器端代码

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> // POSIX标准定义的通用函数,如close()
#include <arpa/inet.h> // 提供inet相关的函数,如inet_addr()
#include <sys/socket.h> // 提供socket相关的函数和数据结构

#define BUF_SIZE 1024
void error_handling(char *message); 

int main(int argc, char *argv[]) 
{   
    FILE *read_fp, *write_fp;
    int serv_sock; // 服务器套接字
    int clnt_sock; // 客户端套接字
    int i,str_len;

    struct sockaddr_in serv_addr; // 服务器地址结构
    struct sockaddr_in clnt_addr; // 客户端地址结构
    socklen_t clnt_addr_size; // 客户端地址结构的大小
    
    char message[BUF_SIZE]; // 要发送给客户端的消息

    
    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; // 地址族设置为IPv4
    serv_addr.sin_addr.s_addr=htonl(INADDR_ANY); // 服务器地址设置为任意
    serv_addr.sin_port=htons(atoi(argv[1])); // 设置监听端口为命令行参数指定的端口

    // 绑定套接字,调用bind()函数分配ip地址和端口号
    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_size=sizeof(clnt_addr);
    for(i=0;i<5;i++){
        clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
        if(clnt_sock==-1)
            error_handling("accept() error");
        else{
            printf("Connected client %d\n", i+1);
        }

        //把文件描述符转换为流
        read_fp = fdopen(clnt_sock, "r");
        write_fp = fdopen(clnt_sock, "w");
        //使用标准I/O函数
        while(!feof(read_fp)){
            fgets(message, BUF_SIZE, read_fp);
            fputs(message, write_fp);
            fflush(write_fp);
        }
        fclose(read_fp);
        fclose(write_fp);
    }
   
    
    // 关闭客户端和服务器套接字
    close(serv_sock);
    
    return 0; 
}


void error_handling(char *message)
{
    fputs(message, stderr); 
    fputc('\n', stderr); 
    exit(1); 
}

②客户端代码

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <arpa/inet.h> 
#include <sys/socket.h> 

#define BUF_SIZE 1024
void error_handling(char *message); 

int main(int argc, char *argv[]) 
{   
    FILE *readfp,*writefp;
    int sock; // 客户端套接字
    struct sockaddr_in serv_addr; // 服务器地址结构
    char message[BUF_SIZE]; // 用于存储从服务器接收的消息
    int str_len,i; // 读取的字节数

    
    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; // 地址族设置为IPv4
    serv_addr.sin_addr.s_addr = inet_addr(argv[1]); // 设置服务器IP地址
    serv_addr.sin_port = htons(atoi(argv[2])); // 设置服务器端口号

    // 发送连接请求
    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1)
        error_handling("connect() error"); 
        else{
            printf("Connected.....\n");
        }

    //把文件描述符转换为流
    readfp = fdopen(sock, "r");
    writefp = fdopen(sock, "w");
    //使用标准I/O函数
    while(1){
        fputs("Input message(Q to quit): ", 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){
    fputs(message, stderr); 
    fputc('\n', stderr); 
    exit(1); 
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

依赖自动装配

黑马程序员SSM框架 文章目录 1、依赖自动装配2、依赖自动装配的特征 1、依赖自动装配 IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配自动装配方式 按类型&#xff08;常用&#xff09;按名称按构造方法不启用自动装配 配置中使用bean标签auto…

68. UE5 RPG 优化敌人角色的表现效果

我们现在已经有了四个敌人角色&#xff0c;接下来&#xff0c;处理一下在战斗中遇到的问题。 处理角色死亡后还会攻击的问题 因为我们有角色溶解的效果&#xff0c;角色在死亡以后的5秒钟才会被销毁掉。所以在这五秒钟之内&#xff0c;角色其实还是会攻击。主要时因为AI行为树…

flash介绍(zynq篇)

简介&#xff1a;Flash存储器&#xff08;又称闪存&#xff09;是一种非易失性存储器. 页是读写的基本操作单位。&#xff08;页写前需要进行擦除操作&#xff08;全部为1&#xff09;&#xff0c;写操作是实现1→0操作&#xff09; 注意&#xff1a;zynq中有板载flash控制器的…

服务部署:Linux系统部署C# .NET项目

1. 安装 .NET SDK 首先&#xff0c;你需要在你的 Linux 系统上安装 .NET SDK。 Ubuntu系统&#xff1a; 下载 Microsoft 包配置文件 wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb 这个命令使用 wge…

大模型Prompt-Tuning技术入门

Prompt-Tuning方法 1 NLP任务四种范式 目前学术界一般将NLP任务的发展分为四个阶段&#xff0c;即NLP四范式&#xff1a; 第一范式&#xff1a;基于「传统机器学习模型」的范式&#xff0c;如TF-IDF特征朴素贝叶斯等机器算法&#xff1b;第二范式&#xff1a;基于「深度学习模…

java打印99乘法表

public class NineNineMulTable{public static void main(String[] args){for(int i 1; i < 9; i ){for(int j 1; j < i; j ){System.out.print(j " * " i " " i * j "\t");//再次先输出j在输出i是打印出来是1*2&#xff0c;2*2}S…

网络安全技术实验六 入侵检测技术实践

一、实验目的和要求 理解基于网络的入侵检测系统的基本原理&#xff0c;掌握snort IDS工作机理&#xff1b; 学习应用snort三种方式工作&#xff1b;熟练编写snort规则&#xff1b; 完成snort数据包记录、日志查看、字符串匹配、ARP欺骗攻击检测、端口扫描工具检测等功能。 …

【计算机视觉】人脸算法之图像处理基础知识(二)

图像处理基础知识&#xff08;二&#xff09; 1.图像的颜色空间转换 我们常见的图像通常由R&#xff08;红色&#xff09;、G&#xff08;绿色&#xff09;、B&#xff08;蓝色&#xff09;组成。但是在很多时候我们会将彩色图像转换成灰度图像进行处理。此时会用到cv2.cvtCo…

C#观察者模式应用

目录 一、什么是观察者模式 二、C#中观察者模式的实现 三、两种实现的用法 1、事件与委托 2、IObserver和IObservable 四、参考文献 一、什么是观察者模式 观察者&#xff08;Observer&#xff09;模式的定义&#xff1a;指多个对象间存在一对多的依赖关系&#xff0c;当…

AGI 远不止 ChatGPT!一文入门 AGI 通识及应用开发

AI 大语言模型进入爆发阶段 2022 年 12 月 ChatGPT 突然爆火&#xff0c;原因是其表现出来的智能化已经远远突破了我们的常规认知。虽然其呈现在使用者面前仅仅只是一个简单的对话问答形式&#xff0c;但是它的内容化水平非常强大&#xff0c;甚至在某些方面已经超过人类了&am…

WordPress插件数据库批量替换内容工具插件

1、安装插件后&#xff0c;我们就可以在后台菜单看到工具操作界面 2、目前支持网站内容、标题、评论指定字符的快速替换 3、可以快速解决以往我们需要从MYSQL数据库命令替换的烦恼

聊聊DoIP吧(三)-端口号port

DoIP在UDP和TCP建立连接和发送诊断报文的过程中使用的端口定义如下&#xff1a;

通过腾讯云TDSQL TCPTCE(MySQL版)认证考试秘籍宝典

腾讯云TDSQL(MySQL版)交付运维高级工程师TCCP证书展示 腾讯云TDSQL(MySQL版)交付运维专家TCCE考试成绩、证书展示 认证类型与级别 TCCA:入门级(初级) TCCP:高级(中级) TCCE:专家级(高级) 考试形式 考试是在线考试&#xff0c;考生需要在腾讯云大学官网上完成。 腾讯云TDSQ…

最新情侣飞行棋高阶羞羞版,解锁私密版情侣小游戏,文末有福利!

今天要跟大家聊聊一种特别有意思的游戏——情侣飞行棋羞羞版。别急着脸红&#xff0c;这可是专为情侣设计的游戏&#xff0c;让你们在轻松愉快的氛围中&#xff0c;增进了解&#xff0c;加深感情。 谈恋爱&#xff0c;不就是两个人在一起&#xff0c;做些有趣的事情吗&#xf…

鸿蒙开发:【设置任务快照的图标和名称】

设置任务快照的图标和名称 设置任务快照的图标和名称是为了提高用户界面的可视化性和用户体验&#xff0c;以便更好地管理和跟踪应用程序中的任务和功能。通过为每个任务快照设置不同的图标和名称&#xff0c;可以更轻松地区分和识别每个任务的功能。 默认情况下任务快照的图…

江协科技51单片机学习- p7 独立按键控制LED灯

前言&#xff1a; 本文是根据哔哩哔哩网站上“江协科技51单片机”视频的学习笔记&#xff0c;在这里会记录下江协科技51单片机开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了江协科技51单片机教学视频和链接中的内容。 引用&#xff1a; 51单片机入门教程-2…

SAP FI 批量显示科目余额 发生额的报表

实际界面 结果 源代码 *&---------------------------------------------------------------------* *& Report ZRPT_FICO_F01 *&---------------------------------------------------------------------* *& 20240614 批量显示余额 发生额 *&---------…

Python | Leetcode Python题解之第149题直线上最多的点数

题目&#xff1a; 题解&#xff1a; class Solution:def maxPoints(self, points: List[List[int]]) -> int:n len(points)if n < 2:return nres 2for i in range(n):x1, y1 points[i][0], points[i][1]has {}for j in range(i 1, n):x2, y2 points[j][0], points…

[Java基本语法] 异常

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (92平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;线程与…

从0到1:手动测试迈向自动化——手机web应用的自动化测试工具

引言&#xff1a; 在当今移动互联网时代&#xff0c;手机web应用已经成为人们生活中不可或缺的一部分。为了保证手机web应用的质量和稳定性&#xff0c;自动化测试工具变得十分重要。本文将介绍手机web应用自动化测试工具的选择和使用&#xff0c;提供一份超详细且规范的指南&a…