37
SOCKET发送数据格式的那点事
文章分类:编程开发
发表日期:2010/04/22 21:04
总点击数:132
总评论数:0
发表日期:2010/04/22 21:04
总点击数:132
总评论数:0
前几天帮一MM做课程设计,要用到windows socket,之前没有学过windows socket编程,编程过程中遇到很多问题。
本文记录我遇到的socket发送数据包的格式问题。
代码简化如下:
这段代码有什么问题吗?
实际情况是:运行时send调用失败,返回错误码为10014,MSDN上解释:The buf parameter is not completely contained in a valid part of the user address space.
为什么会出现这个问题呢?
原来是我犯了一个逻辑错误。
先看看send的原形:
这就说明buf中的数据在内存中要连续,否则就会发送错误的数据。
上面给出的代码刚好在这点犯了错误,team的pPersonArray是new出来的,它的地址是不确定的,这就导致send发送的数据是错误的,尽管成功发送了正确的nCount和pPersonArray指针(地址),但剩下发送的team.nCount*sizeof(SPERSON)字节数据是没有意义的数据,并不是辛辛苦苦new初来的那块。
那么,socket发送的数据要怎样封装呢?包的结构最好是什么样的?
我在CSDN上发帖求救,得到一些指点(帖子链接)。
结合自己的项目实践,总结如下:
到这里,修正上面给出的问题代码:
感觉socket也没什么大不了的,数据的传送和接收而已(呵呵,个人见解)。
本文记录我遇到的socket发送数据包的格式问题。
代码简化如下:
struct SPERSON
{
int nWeight;
char szName;
};
struct STEAM
{
int nCount; // person的个数
SPERSON* pPersonArray; // SPERSON组成的数组指针
};
STEAM team;
team.nCount = 10;
team.pPersonArray = new SPERSON[team.nCount];
// 其他初始化操作省略
// ...
send(sock, (char*)&team, sizeof(STEAM)+team.nCount*sizeof(SPERSON));
这段代码有什么问题吗?
实际情况是:运行时send调用失败,返回错误码为10014,MSDN上解释:The buf parameter is not completely contained in a valid part of the user address space.
为什么会出现这个问题呢?
原来是我犯了一个逻辑错误。
先看看send的原形:
int send( SOCKET s, const char FAR* buf, int len, int flags ); Parameters s [in] Descriptor identifying a connected socket. buf [in] Buffer containing the data to be transmitted. len [in] Length of the data in the buf parameter. flags [in] Indicator specifying the way in which the call is made.其实,send将从开始发送buf中的len字节数据。
这就说明buf中的数据在内存中要连续,否则就会发送错误的数据。
上面给出的代码刚好在这点犯了错误,team的pPersonArray是new出来的,它的地址是不确定的,这就导致send发送的数据是错误的,尽管成功发送了正确的nCount和pPersonArray指针(地址),但剩下发送的team.nCount*sizeof(SPERSON)字节数据是没有意义的数据,并不是辛辛苦苦new初来的那块。
那么,socket发送的数据要怎样封装呢?包的结构最好是什么样的?
我在CSDN上发帖求救,得到一些指点(帖子链接)。
结合自己的项目实践,总结如下:
最好先定义一个结构体,记录数据包的摘要性信息,最重要的是数据包的大小(字节)。
这样,当接收端收到并解析这个摘要信息后,就会知道数据包的具体字节。
然后,再发送数据包,千万注意,每次send的数据必须在内存上是连续的。
这样,就可以正确发送、接收、解析了。
这样,当接收端收到并解析这个摘要信息后,就会知道数据包的具体字节。
然后,再发送数据包,千万注意,每次send的数据必须在内存上是连续的。
这样,就可以正确发送、接收、解析了。
到这里,修正上面给出的问题代码:
struct SPERSON
{
int nWeight;
char szName;
};
struct STEAMBRIEF
{
int nCount; // person的个数
};
STEAMBRIEF teamBrief;
teamBrief.nCount = 10;
SPERSON* pPersonArray = new SPERSON[teamBrief.nCount];
// 其他初始化操作省略
// ...
// 先发送摘要信息
send(sock, (char*)&teamBrief, sizeof(STEAMBRIEF));
// 再发送具体数据
send(sock, (char*)pPersonArray, teamBrief.nCount*sizeof(SPERSON));
客户端可以这么处理:
// 首先接收摘要信息 char* pBriefBuffer = new char[sizeof(STEAMBRIEF)]; recv(sock, pBriefBuffer, sizeof(STEAMBRIEF)); // 解析摘要信息 STEAMBRIEF* pBrief = (STEAMBRIEF*)pBriefBuffer; // 接收真正数据 // person的个数 int nCount = pBrief->nCount; char* pPersonArrayBuffer = new char[nCount*sizeof(SPERSON)]; recv(sock, pPersonArrayBuffer, nCount*sizeof(SPERSON)); SPERSON* pPersonArray = (SPERSON*)pPersonArrayBuffer;解决了这个问题,后面的代码就很顺利了。
感觉socket也没什么大不了的,数据的传送和接收而已(呵呵,个人见解)。
感谢小妹妹给了我这次学习socket编程的机会。。。
2010-04-22 于 湖南长沙中南大学
2010-04-22 于 湖南长沙中南大学
请尊重版权,转载请注明出处;代码及文章如需用于商业用途需经本人同意
本文永久链接:http://www.outsky.org/article.php?action=read&category=1400&page=1&id=37






