void CCAsyncSocketDlg::OnBnClickedBtnSend()
{
UpdateData(TRUE);
TCHAR ipstr[INET_ADDRSTRLEN];
DWORD dwRemoteIp = htonl(m_dwRemoteIp);
InetNtop(AF_INET, &dwRemoteIp, ipstr, sizeof ipstr)); int nWrite = m_sockLocal.SendToEx(m_strSend.GetBuffer(), m_strSend.GetLength(),
htons(m_uRemotePort), ipstr);
}
void CCAsyncSocketDlg::OnReceive(int nErrorCode)
{
UpdateData(TRUE);
TCHAR buf[];
int nRead;
CString rAddr;
UINT rPort;
while (true)
{
nRead = m_sockRemote.ReceiveFromEx(buf, , rAddr, rPort);
if (nRead > )
{
buf[nRead] = ;
m_strRecv.Append(buf);
}
else
{
break;
}
} m_strRecv.Append(_T("\r\n"));
UpdateData(FALSE);

上述代码是忽略了错误处理后的代码,其中Dlg类的OnReceive方法是给CAsyncSocket的派生类的OnReceive方法调用的(在此之前派生类保存了Dlg类的指针)。

由于是UDP套接字,所以不存在粘包问题,SendTo和RecvFrom的返回值是一样的(说明发送和接收的数据大小一样),那么后面部分怎么出错的呢?

经过多次输入测试,发现每次只有后半部分读取失败。解决方法如下

    int nWrite = m_sockLocal.SendToEx(m_strSend, m_strSend.GetLength() * sizeof(TCHAR),
htons(m_uRemotePort), ipstr);
            buf[nRead / sizeof(TCHAR)] = ;

替换对应位置即可,因为我是传递TCHAR数组(在Unicode下CString是基于TCHAR的,如果用char的话每次CA2W、CW2A还是挺麻烦的),而socket传递的是以字节为单位,对于包含N个字符的TCHAR数组,实际上传输字节数是N*sizeof(TCHAR),所以SendTo函数里第二个参数妖改成sizeof(TCHAR),但是对于接收缓冲区而言,缓冲区是个TCHAR数组,单位大小是sizeof(TCHAR)个字节而不是1个字节,所以计算下标时又要用nRead / sizeof(TCHAR)。

顺便TCHAR的字符串操作函数相当于就是把strxxx改成了_tcsxxx,比如标准C的strcpy对于TCHAR来说就是_tcscpy,这是微软对Unicode字符操作函数的扩展,见头文件tchar.h

以及inet_ntop等网络转换函数也变成了InetNtop,见头文件WS2tcpip.h。

这个类本身使用不难,但是由于书上包括文档有不少东西没说清楚,结果折腾了好久。顺带一提,它的一系列函数使用的IP也好,接口也好,竟然还是要用htons、htonl转换的,唉,真是无语。

CAsyncSocket只传输了一部分数据(UDP),后面是乱码的更多相关文章

  1. [TCP/IP] 传输层-TCP和UDP的使用场景

    传输层-TCP和UDP应用场景 TCP(传输控制协议) 需要将要传输的文件分段传输,建立会话,可靠传输,流量控制 UDP(用户报文协议) 一个数据包就能完成数据通信,不需要建立会话,不分段,不用流量控 ...

  2. 【知识强化】第五章 传输层 5.2 UDP协议

    这节课我们来学习一下UDP协议. 那在上节课呢我们学了这样一个打油诗. 啊,就是传输层有两个好兄弟,大哥TCP和二弟UDP.大哥很靠谱,二弟不靠谱.那只要说到UDP协议我们就要知道它的一个重要的特点, ...

  3. 1   开发一个注重性能的JDBC应用程序不是一件容易的事. 当你的代码运行很慢的时候JDBC驱动程序并不会抛出异常告诉你。   本系列的性能提示将为改善JDBC应用程序的性能介绍一些基本的指导原则,这其中的原则已经被许多现有的JDBC应用程序编译运行并验证过。 这些指导原则包括:    正确的使用数据库MetaData方法    只获取需要的数据    选用最佳性能的功能    管理连

    1 开发一个注重性能的JDBC应用程序不是一件容易的事. 当你的代码运行很慢的时候JDBC驱动程序并不会抛出异常告诉你. 本系列的性能提示将为改善JDBC应用程序的性能介绍一些基本的指导原则,这其中的 ...

  4. Linux rsync配置用于服务器之间传输大量的数据

    Linux的rsync 配置,用于服务器之间远程传大量的数据   [教程主题]:rsync [课程录制]: 创E [主要内容] [1] rsync介绍 Rsync(Remote Synchronize ...

  5. Excel只想显示一部分日期,怎样把其余部分隐藏起来?

      问题:只想显示一部分日期,怎样把其余部分隐藏起来? 方法:分列 Step1:选中需要修改的单元格——数据——分列. Step2:固定宽度——点击下一步. Step3:在建立分列处单击鼠标(若想取消 ...

  6. img只显示图片一部分 或 css设置背景图片只显示图片指定区域

    17:14 2016/3/22img只显示图片一部分 或 css设置背景图片只显示图片指定区域 background-position: 100% 56%; 设置背景图片显示图片的哪个坐标区域,图片左 ...

  7. wcf传输Dataset大数据量 -压缩(一)

    wcf传输Dataset大数据量 -压缩(一) 由于WCF不能传输DataTable(不能序列化),所以更多项目中都会使用DataSet作为查询集合的首选返回类型,但是由于DataSet会生成很多的状 ...

  8. oracle 查询重复数据并且删除, 只保留一条数据

    数据库操作中,经常会因为导数据造成数据重复,需要进行数据清理,去掉冗余的数据,只保留正确的数据 一:重复数据根据单个字段进行判断 1.首先,查询表中多余的数据,由关键字段(name)来查询. sele ...

  9. hbase使用MapReduce操作3(实现将 fruit 表中的一部分数据,通过 MR 迁入到 fruit_mr 表中)

    Runner类 实现将 fruit 表中的一部分数据,通过 MR 迁入到 fruit_mr 表中. package com.yjsj.hbase_mr; import org.apache.hadoo ...

随机推荐

  1. [Android]如何减小APK的大小

    能不引用的外部包就不用,删除没用的图片.xml,优化代码去掉没用的部分,能异步下载的资源就运行时从网络上下载.

  2. 十六、dbms_space_admin(提供了局部管理表空间的功能)

    1.概述 作用:提供了局部管理表空间的功能 2.包的组成 1).segment_verify作用:用于检查段的区映像是否与位图一致语法:dbms_space_admin.segment_verify( ...

  3. LeetCode OJ:H-Index(H指数)

    Given an array of citations (each citation is a non-negative integer) of a researcher, write a funct ...

  4. Python中函数练习

    练习1:编写一个函数,接收一个字符串参数,返回一个元组(第一个元素为大写字母的个数,第二个元素为小写字母的个数) 解析:  练习二:编写函数,计算字符串匹配的准确率(orginStr为原始内容,use ...

  5. 求序列完美度(trie+贪心)

    题目链接: 求序列完美度 题目描述 给出由n个数组成的序列s,规定第i个数s[i]到第j个数s[j]组成的子序列的完美度为该子序列中所有数的和与任意一个不在该子序列中的数进行异或运算得到的值中的最大值 ...

  6. 单独编译某个pas文件

    默认的询问.提示.警告框都是英文,找到Vcl.consts.pas改了下,重新编译,放到安装目录下,替换原有的即可. 1. 使用dcc32.exe编译指定的pas文件,dcc32.exe所在目录见下图 ...

  7. 报错【Expression user.achievement is undefined on 】

  8. IIS项目发布完整流程

    第一步: 发布项目 使在IIS上发布是防止源码泄露 第二步: 打开IIS(如果没有就自己安装一个)打开IIS步骤 控制面板>系统安全>管理工具>IIS管理器 填写网站的名称和之前发布 ...

  9. 剑指offer第五章

    剑指offer第五章 1.数组中出现次数超过一半的数 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字. 例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组 ...

  10. JavaScript中字符串截取函数slice()、substring()、substr()

    在js中字符截取函数有常用的三个slice().substring().substr()了,下面我来给大家介绍slice().substring().substr()函数在字符截取时的一些用法与区别吧 ...