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)所说,但一旦接受后对方机器无法正确解析,甚至程序崩溃。

【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反思与思考】

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

未完待续。

作者:铭毅天下

转载请标明出处,原文地址:http://blog.csdn.net/laoyang360/article/details/47342541

如果感觉本文对您有帮助,请点击‘顶’支持一下,您的支持是我坚持写作最大的动力,谢谢!

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-08 01:28:21

Socket传输结构体数据注意事项的相关文章

Linux网络编程之socket相关结构体

Linux中的网络编程是通过 Socket (套接字)实现. Socket有三种类型: 流式套接字(SOCK_STREAM) 流式套接字可以提供可靠的.面向连接的通讯流,它使用TCP协议.TCP保证了数据传输的正确性和顺序性. 数据报套接字(SOCK_DGRAM) 数据报套接字定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证可靠,无差错,它使用数据报协议UDP. 原始套接字(SOCK_RAM) 原始套接字允许使用IP协议,主要用于新的网络协议的测试等. Socket

剔除list中相同的结构体数据

剔除list中相同的结构体数据,有三个思路: 1.两层循环,逐个比较 2.使用set容器来剔除 3.使用unique方法去重 // deduplication.cpp : 定义控制台应用程序的入口点. // #include <list> #include <set> #include <iostream> #include <algorithm> #include <vector> #include <tchar.h> using

C与C# socket 跨平台通讯传输结构体

最近需要写一个C组成的服务器端与C#的客户端进行交互的软件,刚开始写的时候发现C#端解析时候出现了故障,经过仔细研究后发现原因是发送方传输太快,出现了所谓粘包的现象.也就是在C#端的Receive().这个函数返回的是多个结构体连起来的数据,这当然是无法解析的.我的解决方案如下: List<byte[]> listb = new List<byte[]>(); .......... int recv = newclient.Receive(b1); for (int x = 0;

C#引用c++DLL结构体数组注意事项(数据发送与接收时)

本文转载自:http://blog.csdn.net/lhs198541/article/details/7593045 最近做的项目,需要在C# 中调用C++ 写的DLL,因为C# 默认的编码方式是Unicode,而调用的DLL规定只处理UTF8编码格式的字符串,DLL中的输入参数类型char*被我Marshal成byte[],输出参数类型char**被我Marshal成了string(C++和C#之间的类型转换请参阅相关资料),于是我就经历了无数次用于接收时的string-->string(

C++ socket 传输不同类型数据的四种方式

使用socket传输组织好的不同类型数据,有四种不同的方式(我知道的嘿嘿): a. 结构体 b. Json序列化 c. 类对象 d. protobuf 下面逐一整理一下,方便以后进行项目开发. 1. 使用结构体 假设需要传送的结构体如下: struct person { char name[20]; // 注意:CPU访问内存的时候,对访问地址有对齐的要求,一般为2的幂次方.所以,有的数据被填充,以满足对齐要求. int age; float high; }; 可在发送数据的地方对数据进行处理,

IplImage结构体数据解析

IplImage 由于OpenCV主要针对的是计算机视觉方面的处理,因此在函数库中,最重要的结构体是IplImage结构.IplImage结构来源于Intel的另外一个函数库Intel Image Processing Library (IPL),该函数库主要是针对图像处理. typedef struct _IplImage { int nSize; /* IplImage大小 */ int ID; /* 版本 (=0)*/ int nChannels; /* 大多数OPENCV函数支持1,2,

vector存放结构体数据的2种方法

如果要在Vector容器中存放结构体类型的变量,经常见到两种存放方式. 方式一:放入这个结构体类型变量的副本. 方式二:放入指向这个结构体类型变量的指针. 假设结构体类型变量是这样的, typedef struct student{ char school_name[100]; char gender; int age; bool is_absent; } StudentInfo; 那么,方式一和方式二的实现分别如下所示: /*[方式一] 结构体放栈中,vector中放副本-----------

C# Socket 入门4 UPD 发送结构体(转)

今天我们来学 socket  发送结构体 1. 先看要发送的结构体 using System;using System.Collections.Generic;using System.Text;using System.Runtime.InteropServices; namespace Lin.p2p.Mo{    /// <summary>    /// 通信消息格式    /// </summary>    [Serializable]    [StructLayout(L

[C#技术参考]Socket传输结构数据

最近在做一个机器人项目,要实时的接收机器人传回的坐标信息,并在客户端显示当前的地图和机器人的位置.当然坐标的回传是用的Socket,用的是C++的结构体表示的坐标信息.但是C#不能像C++那样很easy的把字节数组byte[]直接的转换成结构,来发送和接收.在C#中要多做一些工作.但是在C或者C++中这是一件很容易的事,只需要一个函数: void *memcpy(void *dest, const void *src, size_t n);//从源src所指的内存地址的起始位置开始拷贝n个字节到