TCP显式编码报文长度发送与接收

报文格式最重要的是如何确定报文的边界。常见的报文格式有两种方法,一种是发送端把要发送的报文长度预先通过报文告知给接收端;另一种是通过一些特殊的字符来进行边界的划分。
这篇文章中讲的是发送报文长度的方法。报文类型如下:
在这里插入图片描述

第一部分是4个字节大小的消息长度,其目的是将真正发送的字节流的大小显式通过报文告知接收端,第二部分是 4 个字节大小的消息类型,第2部分才是真正需要发送的数据。

发送端

readnMessageByLength.c里边的代码如下:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<errno.h>
#include<syslog.h>
#include<signal.h>
size_t readn(int fd, void *buffer, size_t length);
size_t read_message(int fd, char *buffer, size_t length);static int count;static void sig_int(int signo) {printf("\nreceived %d datagrams\n", count);exit(0);
}int main(int argc, char **argv) {if (argc != 2) {printf("usage: select01 <IPaddress> or <Port>\n");}int listenfd;listenfd = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in server_addr;memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = htonl(INADDR_ANY);server_addr.sin_port=htons(atoi(argv[1]));int on = 1;setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));int rt1 = bind(listenfd, (struct sockaddr *) &server_addr, sizeof(server_addr));if (rt1 < 0) {printf("bind failed");exit(errno);}int rt2 = listen(listenfd, 5);if (rt2 < 0) {printf("listen failed");exit(errno);}signal(SIGPIPE, SIG_IGN);int connfd;struct sockaddr_in client_addr;socklen_t client_len = sizeof(client_addr);if ((connfd = accept(listenfd, (struct sockaddr *) &client_addr, &client_len)) < 0) {printf("bind failed");exit(errno);}char buf[128];count = 0;while (1) {int n = read_message(connfd, buf, sizeof(buf));if (n < 0) {printf("error read message\n");exit(errno);} else if (n == 0) {printf("client closed \n");exit(0);}buf[n] = 0;printf("received %d bytes: %s\n", n, buf);count++;}exit(0);}size_t readn(int fd, void *buffer, size_t length) {size_t count;ssize_t nread;char *ptr;ptr = buffer;count = length;while (count > 0) {nread = read(fd, ptr, count);if (nread < 0) {if (errno == EINTR)continue;elsereturn (-1);} else if (nread == 0)break;                /* EOF */count -= nread;ptr += nread;}return (length - count);        /* return >= 0 */
}size_t read_message(int fd, char *buffer, size_t length) {u_int32_t msg_length;u_int32_t msg_type;int rc;rc = readn(fd, (char *) &msg_length, sizeof(u_int32_t));if (rc != sizeof(u_int32_t))return rc < 0 ? -1 : 0;msg_length = ntohl(msg_length);rc = readn(fd, (char *) &msg_type, sizeof(msg_type));if (rc != sizeof(u_int32_t))return rc < 0 ? -1 : 0;if (msg_length > length) {return -1;}rc = readn(fd, buffer, msg_length);if (rc != msg_length)return rc < 0 ? -1 : 0;return rc;
}

gcc readnMessageByLength.c -o readnMessageByLength编译,./readnMessageByLength 8080运行。

接收端

SendMessageByLength.c里边的代码如下:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<errno.h>
#include<syslog.h>
#include<signal.h>
int main(int argc, char **argv) {if (argc != 3) {printf("usage: tcpclient <IPaddress>\n");exit(errno);}int socket_fd;socket_fd = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in server_addr;bzero(&server_addr, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(atoi(argv[2]));;inet_pton(AF_INET, argv[1], &server_addr.sin_addr);socklen_t server_len = sizeof(server_addr);int connect_rt = connect(socket_fd, (struct sockaddr *) &server_addr, server_len);if (connect_rt < 0) {fprintf(stderr, "error in connect: %s (%d)\n", strerror(errno), errno);exit(errno);}struct {u_int32_t message_length;u_int32_t message_type;char buf[128];} message;int n;while (fgets(message.buf, sizeof(message.buf), stdin) != NULL) {n = strlen(message.buf);message.message_length = htonl(n);message.message_type = 1;if (send(socket_fd, (char *) &message, sizeof(message.message_length) + sizeof(message.message_type) + n, 0) < 0){fprintf(stderr, "error in send: %s (%d)\n", strerror(errno), errno);exit(errno);}}exit(0);
}

gcc SendMessageByLength.c -o SendMessageByLength编译,./SendMessageByLength 127.0.0.1 8080运行。

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

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

相关文章

document

原贴连接 1.在整个文档范围内查询元素节点 功能API返回值根据id值查询document.getElementById(“id值”)一个具体的元素节根据标签名查询document.getElementsByTagName(“标签名”)元素节点数组根据name属性值查询document.getElementsByName(“name值”)元素节点数组根据类…

禁止谷歌浏览器自动更新

禁止谷歌浏览器自动更新 在使用Python包selenium的时候浏览器版版本发生变化后产生很多问题如&#xff1a; 1、直接版本不对应无法运行 2、版本不一致导致debug启动浏览器超级慢 这里是已谷歌浏览器为代表的。 禁止自动更新的方法如下&#xff1a; 1、WinR调出运行&#x…

竞赛选题 题目:基于深度学习的手势识别实现

文章目录 1 前言2 项目背景3 任务描述4 环境搭配5 项目实现5.1 准备数据5.2 构建网络5.3 开始训练5.4 模型评估 6 识别效果7 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的手势识别实现 该项目较为新颖&#xff0c;适合作为竞赛课题…

springboot+java电脑硬件库存管理系统+jsp

现如今&#xff0c;信息种类变得越来越多&#xff0c;信息的容量也变得越来越大&#xff0c;这就是信息时代的标志。近些年&#xff0c;计算机科学发展得也越来越快&#xff0c;而且软件开发技术也越来越成熟&#xff0c;因此&#xff0c;在生活中的各个领域&#xff0c;只要存…

SQL自学通之查询--SELECT语句的使用

一、前言 1、目标 在今天你将学习到以下内容&#xff1a; l 如何写SQL的查询 l 将表中所有的行选择和列出 l 选择和列出表中的选定列 l 选择和列出多个表中的选定列 2、背景 在上篇中我们简要地介绍了关系型数据库系统所具有的强大功能 在对 SQL 进行了 简要的介绍中我们…

[UnityWebGL]修改webgl启动模板

首先了解什么是WEBGGL启动模板&#xff0c;如下图&#xff1a; 其次&#xff0c;启动模板在哪里设置&#xff0c;如下图&#xff1a; 最后&#xff0c;怎么改启动模板里面的内容&#xff08;提供最简单的方式&#xff0c;直接改官方的&#xff09;&#xff1a; 1、首先在Asset…

TypeScript编程语言学习,为学习HarmonyOS开发做准备

1. 编程语言 ArkTS是HarmonyOS优选的应用开发语言&#xff0c;它在TypeScript&#xff08;TS&#xff09;的基础上&#xff0c;匹配ArkUI扩展&#xff0c;扩展了声明式UI、状态管理等相应的能力。 JavaScript&#xff08;JS&#xff09;&#xff0c;使用在Web应用开发&#xf…

RHCSA学习笔记(RHEL8) - Part2.RH134

Chapter Ⅰ 提高命令行生产率 SHELL脚本 #/bin/bash声明使用的shell翻译器 for循环 for VAR in LIST doCOMMAND1COMMAND2 done实验1&#xff1a;显示host1-5 #! /bin/bash for host in host{1..5} doecho $host done实验2&#xff1a;显示包含kernel的软件包安装时间 #! /…

CAN总线学习(STM32的CAN寄存器使用)(笔记二)

CAN总线基础基础知识的文章&#xff1a;CAN总线学习&#xff08;CAN总线基础知识&#xff09;&#xff08;笔记一&#xff09;-CSDN博客 在前面CAN总线基础知识和报文中介绍的是报文内容是比较全面的&#xff0c;STM32在CAN协议的基础上做了一些简单的简化&#xff0c;例如下图…

softmax实现

import matplotlib.pyplot as plt import torch from IPython import display from d2l import torch as d2lbatch_size 256 train_iter,test_iter d2l.load_data_fashion_mnist(batch_size) test_iter.num_workers 0 train_iter.num_workers 0 num_inputs 784 # 将图片…

【MySQL】-日志系统

一、背景介绍 MySQL中提供了各种各样的日志&#xff0c;每一个日志在不同的阶段有不同的作用&#xff0c;对数据的一致性和正确性得到保障&#xff0c;为数据恢复也提供至关重要的作用&#xff0c;那今天我们一起来讨论讨论MySQL中的各个日志 二、正文 binlog&#xff1a;…

NIO--07--Java lO模型详解

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 何为 IO?先从计算机结构的角度来解读一下I/o.再从应用程序的角度来解读一下I/O 阻塞/非阻塞/同步/异步IO阻塞IO非阻塞IO异步IO举例 Java中3种常见的IO模型BIO (Blo…

Redis缓存的使用

什么是缓存 缓存就是数据交换的缓冲区&#xff0c;是存储数据的临时地方&#xff0c;一般读写性能较高。 缓存的作用&#xff1a; 降低后端负载提高读写效率&#xff0c;降低响应时间 缓存的成本&#xff1a; 数据一致性成本代码维护成本运维成本 Redis特点 键值型数据库…

C语言之结构体

一.前言引入. 我们知道在C语言中有内置类型&#xff0c;如&#xff1a;整型&#xff0c;浮点型等。但是只有这些内置类 型还是不够的&#xff0c;假设我想描述学⽣&#xff0c;描述⼀本书&#xff0c;这时单⼀的内置类型是不⾏的。描述⼀个学⽣需要名字、年龄、学号、⾝⾼、体…

Spark经典案例分享

Spark经典案例 链接操作案例二次排序案例 链接操作案例 案例需求 数据介绍 代码如下&#xff1a; package base.charpter7import org.apache.hadoop.conf.Configuration import org.apache.hadoop.fs.{FileSystem, Path} import org.apache.spark.SparkContext import org.a…

四、Zookeeper节点类型

目录 1、临时节点 2、永久节点 Znode有两种,分别为临时节点和永久节点。 节点的类型在创建时即被确定,并且不能改变。 1、临时节点 临时节点的生命周期依赖于创建它们的会话。一旦会话结束,临时节点将被自动删除,

OpenCV-Python:计算机视觉介绍

目录 1.背景 2.计算机视觉发展历史 3.计算机视觉主要任务 4.计算机视觉应用场景 5.知识笔记 1.背景 OpenCV是计算机视觉的一个框架&#xff0c;想要学习OpenCV&#xff0c;需要对计算机视觉有一个大致的了解。计算机视觉是指通过计算机技术和算法来模拟人类视觉系统的能力…

Redis高效缓存:加速应用性能的利器

目录 引言 1. Redis概述 1.1 什么是Redis&#xff1f; 1.2 Redis的特点 2. Redis在缓存中的应用 2.1 缓存的重要性 2.2 Redis作为缓存的优势 2.3 缓存使用场景 3. Redis在实时应用中的应用 3.1 实时数据处理的挑战 3.2 Redis的实时数据处理优势 3.3 实时应用中的Red…

mediapipe+opencv实现保存图像中的人脸,抹去其他信息

mediapipeopencv MediaPipe本身不提供图像处理功能&#xff0c;它主要用于检测和跟踪人脸、手势、姿势等。如果您想要从图像中仅提取人脸主要信息并去除其他信息. # codingutf-8 """project: teatAuthor&#xff1a;念卿 刘file&#xff1a; test.pydate&…

Kubernetes学习笔记-Part.09 K8s集群构建

目录 Part.01 Kubernets与docker Part.02 Docker版本 Part.03 Kubernetes原理 Part.04 资源规划 Part.05 基础环境准备 Part.06 Docker安装 Part.07 Harbor搭建 Part.08 K8s环境安装 Part.09 K8s集群构建 Part.10 容器回退 第九章 K8s集群构建 9.1.集群初始化 集群初始化是首…