llinux C语言在网络编程时使用标准IO

news2024/11/25 0:53:29

目录

fdopen(3)函数

使用标准IO发送数据

使用标准IO接收数据

注意


先看一个简单的TCP客户端程序:

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

int main(void){
	int fd = socket(AF_INET, SOCK_STREAM, 0);
	if(fd == -1){
		perror("socket");
		exit(1);
	}
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(8000);
	addr.sin_addr.s_addr = inet_addr("192.168.1.14");
	if(connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1){
		perror("connect");
		exit(1);
	}
	// 准备写入
	char message[] = "Hello World!";
	char *buf = message;
	int ret, len;
	len = strlen(message);
	while(len != 0 && (ret = write(fd, buf, len)) != 0){
		if(ret == -1){
			if(errno == EINTR) continue; // 写入时收到信号,可以重新写入
			perror("write");
			break;
		}
		len -= ret;
		buf += ret;
	}
	close(fd);
	return 0;
}

可以看到,在发送信息时,使用了这样的代码:

    char message[] = "Hello World!";
	char *buf = message;
	int ret, len;
	len = strlen(message);
	while(len != 0 && (ret = write(fd, buf, len)) != 0){
		if(ret == -1){
			if(errno == EINTR) continue; // 写入时收到信号,可以重新写入
			perror("write");
			break;
		}
		len -= ret;
		buf += ret;
	}

这是因为,使用write(2)函数时,可能会出现写入不全的情况(部分写),因此,需要通过while循环,确保它能全部写完。

但是,这样的代码太麻烦了,有没有简单的办法? 

fdopen(3)函数

我们知道,在标准IO中,有一个fdopen(3)函数:

#include <stdio.h>
FILE *fdopen(int fd, const char *mode);

这个函数将会把一个文件描述符转换成一个文件指针。参数中,fd是文件描述符,mode是操作模式,如"r+"。可以设置为"w"或"w+",但不会清空文件。如果把socket(2)函数返回的文件描述符改成文件指针,就可以通过fprintf等方法直接输出了。

使用标准IO发送数据

我们可以修改代码如下:

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

int main(void){
	int fd = socket(AF_INET, SOCK_STREAM, 0);
	if(fd == -1){
		perror("socket");
		exit(1);
	}
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(8000);
	addr.sin_addr.s_addr = inet_addr("192.168.1.14");
	if(connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1){
		perror("connect");
		exit(1);
	}
	FILE *fp = fdopen(fd, "r+");
	fprintf(fp, "Hello World!");
	fclose(fp);
	return 0;
}

可以看到,采用标准IO,代码就简单了很多。而且,使用标准IO,也可以避免操作底层的时候出现一些问题(如部分写)

我们可以用网络调试助手看一下使用了这种方法是否可以正常发送:

可以看到,它能够正常发送数据,并正常关闭套接字。

使用标准IO接收数据

我们还可以让它能够读取数据:

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

int main(void){
	int fd = socket(AF_INET, SOCK_STREAM, 0);
	if(fd == -1){
		perror("socket");
		exit(1);
	}
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(8000);
	addr.sin_addr.s_addr = inet_addr("192.168.1.14");
	if(connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1){
		perror("connect");
		exit(1);
	}
	FILE *fp = fdopen(fd, "r+");
	char buf[1024];
	fgets(buf, 1024, fp);
	printf("data is %s\n", buf);
	fclose(fp);
	return 0;
}

 使用网络调试助手发送数据(注意要在数据后面加入换行符):

终端输出:

data is Hello Client.

注意

标准IO的设计主要是为了文件读写,将其应用与网络编程并不总是最佳选择。另外需要注意,使用了fdopen(3)函数后,不应直接操作文件描述符(虽然这是合法的),这可能会导致数据竞争等未定义行为。

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

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

相关文章

【数据结构和算法初阶(C语言)】队列实操(概念实现+oj题目栈和队列的双向实现以及循环链表难点题目详解!)

目录 1. 队列的概念及结构 2.队列结构存在的意义应用 3.队列实现的结构选择 4.队列实现 5.队列对数据的处理 5.1队列初始化 5.2队尾入数据 5.3队头出数据 5.4获取队列尾部元素 5.5获取队列头部元素 5.6获取队列中元素个数 5.7检测队列是否为空 5.8销毁队列 6.循环队列补充 7.使…

C语言之快速排序

目录 一 简介 二 代码实现 快速排序基本原理&#xff1a; C语言实现快速排序的核心函数&#xff1a; 三 时空复杂度 A.时间复杂度 B.空间复杂度 C.总结&#xff1a; 一 简介 快速排序是一种高效的、基于分治策略的比较排序算法&#xff0c;由英国计算机科学家C.A.R. H…

矩阵中移动的最大次数

文章目录 所属专栏:BFS算法 题目链接 思路如下&#xff1a; 1.首先我们需要从第一列开始遍历&#xff0c;寻找每一个都能够满足条件的位置&#xff0c;将它插入到数组里面 2.第一列遍历完了后我们先判断第一列的数是否都满足条件插入到数组里面&#xff0c;如果数组为空&#…

03.事件进阶

一、事件流 事件流是对事件执行过程的描述&#xff0c;了解事件的执行过程有助于加深对事件的理解&#xff0c;提升开发实践中对事件运用的灵活度。 如上图所示&#xff0c;任意事件被触发时总会经历两个阶段&#xff1a;【捕获阶段】和【冒泡阶段】。 简言之&#xff0c;捕获…

肝了三天,完成了AIGC工具网站大全,建议收藏再看

说是肝了三天&#xff0c;其实远远不止&#xff0c;前前后后&#xff0c;从资料搜集到最后整理成文&#xff0c;有近一个月了&#xff0c;大家看在整理不易的份上&#xff0c;给点个赞吧&#xff0c;不要光顾着收藏呀&#xff01; 国内网站 AIGC 导航 https://www.aigc.cn 网…

wayland(xdg_wm_base) + egl + opengles 渲染使用纹理贴图的旋转 3D 立方体实例(十三)

文章目录 前言一、使用 stb_image 库加载纹理图片1. 获取 stb_image.h 头文件2. 使用 stb_image.h 中的相关接口加载纹理图片3. 纹理图片——cordeBouee4.jpg二、渲染使用纹理贴图的旋转 3D 立方体1. egl_wayland_texture_cube.c2. Matrix.h 和 Matrix.c3. xdg-shell-client-pr…

使用 pnpm 搭建 monorepo 项目

引言 在我之前的开发经历中&#xff0c;并没有实际使用过 Monorepo 管理项目&#xff0c;尽管之前对此有所了解&#xff0c;但并未深入探究。然而&#xff0c;如今许多开源项目都采纳了 Monorepo 方式&#xff0c;对于不熟悉它的开发者来说&#xff0c;阅读和理解这些项目的源…

关于使用过别人的GitHub/Gitee账号提交东西到仓库后,自己的仓库提交失败问题的解决方法

目录 引言 问题出现的原因 问题的解决方法 打开控制面板 方法一&#xff1a; 方法二&#xff1a; 进入Windows凭据管理器 结语 引言 这个问题折磨了我将近三个小时&#xff0c;为了减少有人和我一样走弯路且防止自己忘记解决方法&#xff0c;便有了这篇文章。 问题出现…

【洛谷 P8602】[蓝桥杯 2013 省 A] 大臣的旅费 题解(图论+深度优先搜索+树的直径+链式前向星)

[蓝桥杯 2013 省 A] 大臣的旅费 题目描述 很久以前&#xff0c;T 王国空前繁荣。为了更好地管理国家&#xff0c;王国修建了大量的快速路&#xff0c;用于连接首都和王国内的各大城市。 为节省经费&#xff0c;T 国的大臣们经过思考&#xff0c;制定了一套优秀的修建方案&am…

uv 必备的工具 ps ai 全家桶合集

非常稀有的资源 &#xff0c;必应搜索 易品资源yipinziyuan 可以找到

浅谈如何自我实现一个消息队列服务器(1)——需求分析

文章目录 一、什么是消息队列&#xff1f;二、当下主流的消息队列(MQ)三、自我实现一个消息队列服务器的前期准备——需求分析3.1 核心概念3.2 broker server 核心概念3.2.1、虚拟主机&#xff08;Virtual Host&#xff09;3.2.2、交换机&#xff08;Exchange&#xff09;3.2.2…

如何构建Docker自定义镜像

说明&#xff1a;平常我们使用Docker运行各种容器&#xff0c;极大地方便了我们对开发应用的使用&#xff0c;如MySQL、Redis&#xff0c;以及各种中间件&#xff0c;使用时只要拉镜像&#xff0c;运行容器即可。本文介绍如何创建一个Demo&#xff0c;自定义构建一个镜像。 开…

基于 K8s 容器集群的容灾架构与方案

作者&#xff1a;庄宇 在设计系统架构时&#xff0c;我们必须假设任何组件和任何基础设施可能会在任何时间失效&#xff0c;例如&#xff1a;自然灾害&#xff0c;电力中断&#xff0c;网络中断&#xff0c;错误的系统变更等。为了应对挑战&#xff0c;我们必须设计合适的容灾…

HTML基础:head头部标签包含的8种形式详解

你好&#xff0c;我是云桃桃。 HTML <head> 标签用于定义文档的头部&#xff0c;包含了一些元数据和引用的外部资源&#xff0c;但并不会直接展示在页面上。<head> 标签位于 <html> 标签内部&#xff0c;紧跟在 <html> 开始标签之后&#xff0c;在 &l…

贪心算法(两个实例)

例一&#xff1a;调度问题 问题&#xff1a;由n项任务&#xff0c;每项任务的加工时间已知&#xff0c;从零时刻开始陆续加入一台机器上去加工&#xff0c;每个任务完成的时间是从0时刻到任务加工截至的时间。 求总完成时间&#xff08;所有任务完成时间最短计划方案&#xf…

C语言字符函数和字符串函数详解

Hello, 大家好&#xff0c;我是一代&#xff0c;今天给大家带来有关字符函数和字符串函数的有关知识 所属专栏&#xff1a;C语言 创作不易&#xff0c;望得到各位佬们的互三呦 一.字符函数 在C语言中有一些函数是专门为字符设计的&#xff0c;这些函数的使用都需要包含一个头文…

SQLiteC/C++接口详细介绍之sqlite3类(十七)

返回目录&#xff1a;SQLite—免费开源数据库系列文章目录 上一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;十六&#xff09; 下一篇&#xff1a; SQLiteC/C接口详细介绍之sqlite3类&#xff08;十八&#xff09; ​ 53.sqlite3_trace_v2 函数功能&#x…

EXCEL+PYTHON学习3

1&#xff09; 遍历一个SHEET&#xff0c;无非就是两个循环&#xff0c;rows属性是取得所有行。 fn data3_16.xlsx wb openpyxl.load_workbook(fn) ws wb.active for row in ws.rows:for cell in row:print(cell.value, end )print() 2&#xff09; 返回工作表的最小行数…

【Leetcode-54.螺旋矩阵】

题目&#xff1a; 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5]示例 2&#xff1a; 输入&#xff1…

Day38:安全开发-JavaEE应用SpringBoot框架MyBatis注入Thymeleaf模版注入

目录 SpringBoot-Web应用-路由响应 SpringBoot-数据库应用-Mybatis SpringBoot-模版引擎-Thymeleaf 思维导图 Java知识点 功能&#xff1a;数据库操作&#xff0c;文件操作&#xff0c;序列化数据&#xff0c;身份验证&#xff0c;框架开发&#xff0c;第三方库使用等. 框架…