Socket传输结构体数据注意事项

简介: 【1 背景】在Socket通信中,要传输结构化的数据或者要进行协议数据传输的时候,发送端必须要构造结构体进行数据传输。接收端也必须通过同样的结构体进行解析。但Socket传输结构体数据时候,稍有不慎就会出现:1)解析数据出错;2)接收数据不完整;3)解析为乱码等的Bug。

【2 举例】

如下是接收端解析数据为乱码甚至崩溃的一类常见错误。


结构体也就是一段连续的内存。  但是类似如下的结构体:

typedef struct _PER_SPIDER_INFO

{

UINT nTimeDelay;

UINT nRtnCode;

UINT nUrlPageLen;

char* pszUrlPage;

}PER_SPIDER_INFO;


不能直接通过传输的。

【3 根本原因】

如下:

1)结构体成员pszUrlPage是指针,指向的是结构体以外的内存地址,也就是在结构体PER_SPIDER_INFO外的非连续的地址空间。

2)如果仅传输pszUrlPage,也就是传输了一个地址,在当前进程空间是可以索引到对应的值。但是一旦通过Socket实现网络传输,即出现了跨进程、跨网络的传输,一个地址传输过去,极大可能甚至100%会读到我们不想要的地址空间,读取的值也会出错。一旦该地址空间不允许读,则会导致程序崩溃。(如下图所示)

3)可以传输,正如2)所说,但一旦接受后对方机器无法正确解析,甚至程序崩溃。image.png

【4 Bug解决步骤路演】

Step1: 缩小范围,只传输int数据,ok;但单包含了字符串指针就不可以;基本锁定是字符串这里除了问题。

Step2:字符串指针换成字符串数组,Bug不再出现。说明至少是连续内存这里出了问题。期间 ,怀疑动态分配内存malloc()以及strcpy,memcpy,传输结构体数据的长度出了问题,花了近3个小时排查 。

Step3:进而换成给定长度(大小结合项目定)的字符串数组,Bug解决掉。


【5 修正后】

typedef struct _PER_SPIDER_INFO

{

UINT nTimeDelay;

UINT nRtnCode;

UINT nUrlPageLen;

char szUrlPage[MAX_URL_PATH]

}PER_SPIDER_INFO;

就可以通过socket传输了。


【6反思与思考】

但是不是包含指针的就不能传输了呢?不是的,只要内存处理的得当也是可以的。回头有示例再附上解析。

未完待续。


image.png

相关文章
|
1月前
|
数据处理 C# C++
如何使用C#和C++结构体实现Socket通信
如何使用C#和C++结构体实现Socket通信
|
3月前
|
Oracle 关系型数据库 Java
这个错误是由于在尝试从 Oracle 数据库的 socket 中读取数据时,没有更多的数据可供读取
这个错误是由于在尝试从 Oracle 数据库的 socket 中读取数据时,没有更多的数据可供读取
50 2
|
3月前
|
Oracle 关系型数据库 Java
从 Oracle 数据库的 socket 中读取数据时,没有更多的数据可供读取。这可能是由于以下原因导致的:
【1月更文挑战第26天】【1月更文挑战第125篇】从 Oracle 数据库的 socket 中读取数据时,没有更多的数据可供读取。这可能是由于以下原因导致的:
23 1
|
3月前
|
网络协议 NoSQL Linux
非阻塞socket网络编程之数据收发完整代码示例
非阻塞socket网络编程之数据收发完整代码示例
|
3月前
Socket网络编程练习题二:客户端发送一条数据,接收服务端反馈的消息并打印;服务端接收数据并打印,再给客户端反馈消息
Socket网络编程练习题二:客户端发送一条数据,接收服务端反馈的消息并打印;服务端接收数据并打印,再给客户端反馈消息
|
4月前
|
网络协议 安全 Python
socket客户端和服务端,文件的传输
socket 实现,客户端和服务端,文件的传输
43 1
|
6月前
14.7 Socket 循环结构体传输
在上述内容中笔者通过一个简单的案例给大家介绍了在套接字编程中如何传递结构体数据,本章将继续延申结构体传输,在某些时候例如我们需要传输一些当前系统的进程列表信息,或者是当前主机中的目录文件,此时就需要使用循环结构体传输功能,循环传输结构体的关键点在于,客户端发送结构体数据之前需要通过一次通信来告诉服务端需要接收的次数,当服务端接收到次数时则可利用接收计数器依次循环接收数据直到客户端完整所有数据包的发送。
20 0
14.7 Socket 循环结构体传输
|
6月前
14.6 Socket 应用结构体传输
当在套接字编程中传输结构体时,可以将结构体序列化为字符串(即把结构体的所有成员打包成一个字符串),然后将字符串通过套接字传输到对端,接收方可以将字符串解析为结构体,然后使用其中的成员数据。这种方法通常被称为序列化(Serialization)和反序列化(Deserialization),本章中我们可以采用将一个结构体序列化为一个纯字符串,然后将该字符串通过套接字传输给对端,当对端收到后只需要将字节序强制转换为对等的结构体指针即可实现对该结构的解析。
26 0
14.6 Socket 应用结构体传输
|
14天前
|
安全 Java 数据处理
Python网络编程基础(Socket编程)多线程/多进程服务器编程
【4月更文挑战第11天】在网络编程中,随着客户端数量的增加,服务器的处理能力成为了一个重要的考量因素。为了处理多个客户端的并发请求,我们通常需要采用多线程或多进程的方式。在本章中,我们将探讨多线程/多进程服务器编程的概念,并通过一个多线程服务器的示例来演示其实现。
|
14天前
|
程序员 开发者 Python
Python网络编程基础(Socket编程) 错误处理和异常处理的最佳实践
【4月更文挑战第11天】在网络编程中,错误处理和异常管理不仅是为了程序的健壮性,也是为了提供清晰的用户反馈以及优雅的故障恢复。在前面的章节中,我们讨论了如何使用`try-except`语句来处理网络错误。现在,我们将深入探讨错误处理和异常处理的最佳实践。