CAsyncSocket只传输了一部分数据(UDP),后面是乱码

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[4096];
    int nRead;
    CString rAddr;
    UINT rPort;
    while (true)
    {
        nRead = m_sockRemote.ReceiveFromEx(buf, 4096, rAddr, rPort);
        if (nRead > 0)
        {
            buf[nRead] = 0;
            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)] = 0;

替换对应位置即可,因为我是传递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转换的,唉,真是无语。

时间: 2024-08-07 04:14:34

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

TCP/IP(三):传输层TCP与UDP

TCP协议 概述 TCP协议和UDP协议处于同一层:传输层,但是两者之间有很大的区别,TCP协议具有以下特点: TCP提供可靠的数据传输服务,TCP是面向连接的,即数据在通信之间要先建立连接,结束通信时要释放连接,这也是后面所说的3次握手,4次挥手: TCP是点对点的连接方式,即一条TCP连接两端只能是两个端点: TCP提供可靠的,无差错的,不丢失,不重复,按顺序的服务: TCP提供全双工通信,允许通信双方任何时候都能发送数据,TCP在连接的两端都设置有发送缓存和接收缓存: TCP是面向字节流的

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

[1 背景] 在Socket通信中,要传输结构化的数据或者要进行协议数据传输的时候,发送端必须要构造结构体进行数据传输. 接收端也必须通过同样的结构体进行解析. 但Socket传输结构体数据时候,稍有不慎就会出现:1)解析数据出错:2)接收数据不完整:3)解析为乱码等的Bug. [2 举例] 如下是接收端解析数据为乱码甚至崩溃的一类常见错误. 结构体也就是一段连续的内存. 但是类似如下的结构体: typedef struct _PER_SPIDER_INFO { UINT nTimeDelay;

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

[教程主题]:rsync [课程录制]: 创E [主要内容] [1] rsync介绍 Rsync(Remote Synchronize) 是一个远程资料同步工具,可通过LAN/WAN快速同步多台主机,Rsync使用所为的“Rsync演算法”来使本地主机和远程主机之间达到同步,这个演算法并不是每次都整份传送,它只传送两台计算机之间所备份的资料不同的部分,因此速度相当快. Rsync的优点如下: 1.可以镜像保存整个目录树和文件系统. 2.可以很容易的做到保持原来文件的许可权.时间.软链接等. 3.

Android 自定义Adapter 但listview 只显示第一条数据

楼主让这个问题郁闷了一晚上.....在logcat里明明显示adapter的getview方法里的list大于一条数据 ,但posotion却一直是0.....运行后也只显示list[0]里面的数据....最后的最后原来错误出在布局文件上 我以前的是这样的; <ScrollView android:layout_width="fill_parent" android:layout_height="wrap_content" > <!-- listv

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

17:14 2016/3/22img只显示图片一部分 或 css设置背景图片只显示图片指定区域 background-position: 100% 56%; 设置背景图片显示图片的哪个坐标区域,图片左上角为0,0或0%,0%,右下角为高度和宽度,或100%,100%. clip:rect(300px 100px 300px 0px); 设置显示图片的某个区域,分别是上右下左的顺序设置 部分代码:<style type="text/css">img {position:abs

关于aspxgridview里面过长内容只显示的一部分的处理方案

1 protected void g_Message_CustomColumnDisplayText(object sender, ASPxGridViewColumnDisplayTextEventArgs e) 2 { 3 if (e.Column.FieldName == "字段") 4 { 5 if (e.Value != null) 6 { 7 string cellValue = e.Value.ToString(); 8 if (cellValue.Length >

Mybatis Collection查询集合只出现一条数据

Mybatis Collection查询集合只出现一条数据 1.原因 如果两表联查,主表和明细表的主键都是id的话,明细表的多条只能查询出来第一条. 2.解决办法 级联查询的时候,主表和从表有一样的字段名的时候,在mysql上命令查询是没问题的.但在mybatis中主从表需要为相同字段名设置别名.设置了别名就OK了. 例子: 主表Standard, 从表StandEntity,均有名为id的字段 <resultMap id="StandardAndEntityResultMap"

sql过滤掉重复记录,只保留一条数据

--过滤掉重复记录,只保留一条数据delete from gzfw_yhxxwhere Zjhm in (select Zjhm from gzfw_yhxx group by Zjhm having count(Zjhm) > 1)and rowid not in (select min(rowid) from gzfw_yhxx group by Zjhm having count(Zjhm )>1)

mysql只导出表结构或数据

只导数据不导结构 mysqldump -t 数据库名 -uroot -p > xxx.sql 只导结构不导数据 mysqldump    --opt -d  数据库名 -u -p > xxx.sql 导出数据和表结构 mysqldump 数据库名 -uroot -p > xxx.sql 导出特定表结构 mysqldump -uroot -p -B 数据库名 --table 表名 > xxx.sql 导入数据 source /tmp/xxx.sql mysql只导出表结构或数据