社区
VB基础类
帖子详情
用Winsock1.SendData发10位长字节数组,系统在尾加0,如何不发该0?
lu888
2000-08-24 07:39:00
...全文
62
回复
打赏
收藏
用Winsock1.SendData发10位长字节数组,系统在尾加0,如何不发该0?
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
标准MFC
WinSock
ActiveX控件开
发
实例(II)高级篇
主要利用VARIANT类型作参数进行的网络数据传送和接收,以及SAFEARRAY,BSTR的详细使用方法。 另外还提供该控件在VC,VB下的调用方式以及相关数据的处理。 关键字:ActiveX,Socket,VARIANT, SAFEARRAY,BSTR。 回顾:在上一篇文章《标准MFC
WinSock
ActiveX控件开
发
实例》中我们详细介绍了控件的开
发
过程,以及接口和事件的 添加和响应方法。现在我们将继续上次没有写完的控件继续进行开
发
,并完善作为一个
WinSock
控件应该具备的功能。 二、按照前一篇文章提到的知识,现在我们来添加两个新的接口分别是
Send
Data
()和Get
Data
(),它们看起来如下: //网络数据
发
送,在指定的超时时间内进行
发
送然后返回,成功返回实际
发
送
字节
数,否则返回负数 long CMFC
WinSock
Ctrl::
Send
Data
(const VARIANT FAR&
Data
, const VARIANT FAR&
Data
Type, const VARIANT FAR&
Data
Length, const VARIANT FAR& TimeOut) { // TODO: Add your dispatch handler code here return 0; } //获取数据,并指定获取数据的超时时间,返回实际获取到的数据长度,否则返回负数 long CMFC
WinSock
Ctrl::Get
Data
(VARIANT FAR*
Data
, const VARIANT FAR&
Data
Type, const VARIANT FAR&
Data
MaxLength, const VARIANT FAR& TimeOut) { // TODO: Add your dispatch handler code here return 0; } 两个接口的参数除了第一个参数外,其它都类似。
Send
Data
()是
发
送数据,不要求将数据带回,因此直接用 VARIANT,而Get
Data
()则要求将数据带回来给调用者,因此定义为 VARIANT *类型,第二个参数
Data
Type故名思义是定义所传送或接收数据的类型,第三个参数是传送或接收数据的长度,这里的长度以char作为一个长度,假如传入的类型是int类型,则长度为4,如果定义的是字符串,一个中文字符占用2个长度。最后一个参数,是网络
发
送或读取时的超时时间。 三、为Connect()接口添加源代码,看起来如下: //网络数据
发
送,在指定的超时时间内进行
发
送然后返回,成功返回实际
发
送
字节
数,否则返回负数 long CMFC
WinSock
Ctrl::
Send
Data
(const VARIANT FAR&
Data
, const VARIANT FAR&
Data
Type, const VARIANT FAR&
Data
Length, const VARIANT FAR& TimeOut) { // TODO: Add your dispatch handler code here if(!OnlySock) return -1;//网络尚未开始建立连接 int g
Data
Type = VariantToLong(
Data
Type); long g
Data
Length = VariantToLong(
Data
Length); int gTimeOut = VariantToLong(TimeOut); if(g
Data
Type < 0) return -2; if(g
Data
Length <= 0) return -2; if(gTimeOut < 0) return -2; switch(g
Data
Type) { case 0://默认形式,这时如果
发
现
Data
为整型
数组
,将不进行任何转换,直接把一个int传给一个char传送(数据可能溢出范围) case 1://当指定该值为1时,当Date为长整型
数组
时,将把一个long转换成四个char传送 case 2://当指定该值为2时,当Date为整型
数组
时,将把一个int转换成四个char传送 case 3://当指定该值为3时,当Date为无符号短整型
数组
时,将把一个unsigned short转换成两个char传送 case 4://当指定该值为4时,当Date为BYTE
数组
时,将把一个BYTE转换成一个char传送 case 5://当指定该值为5时,当Date为短整型
数组
时,将把一个short转换成两个char传送 case 6://当指定该值为6时,当Date为浮点型
数组
时,将把一个float转换成四个char传送 case 7://当指定该值为7时,当Date为双精度
数组
时,将把一个double转换成八个char传送 break; default://如果不在上面取值范围内,将按当前的
Data
相应类型进行传送 break; } timeval tv; fd_set fdwrite; int len = 0; long m = 0; long n = 0; long changetype = 0;//将浮点型数据进行类型转换,再进行传送 VARIANT g
Data
; VariantInit(&g
Data
); //送出信息至服务器 FD_ZERO(&fdwrite); tv.tv_sec = gTimeOut;//指定时间后返回 tv.tv_usec = 0; FD_SET(OnlySock,&fdwrite);//是否可以
发
送数据 select(0,NULL,&fdwrite,NULL,&tv); char *buffer = NULL; if(FD_ISSET(OnlySock,&fdwrite)) { switch(
Data
.vt) { case VT_BSTR://按字符串形式
发
送 buffer = _com_util::ConvertBSTRToString(
Data
.bstrVal); break; case VT_BYREF|VT_UI1: //按BYTE*形式
发
送 buffer = new char[g
Data
Length]; memcpy(buffer,
Data
.pbVal,g
Data
Length); break; case VT_BYREF|VT_I1://按 char *
发
送 buffer = new char[g
Data
Length]; memcpy(buffer,
Data
.pcVal,g
Data
Length); break; case VT_ARRAY|VT_I4://以长整型
数组
发
送 g
Data
.vt = VT_I4; if(g
Data
Type!=0)//long = char*4 { //sizeof(long),在这里一个长整型的长度为4个char buffer = new char[g
Data
Length]; for(m=0,n=0; n>24)&0xff; buffer[m++] = (g
Data
.lVal>>16)&0xff; buffer[m++] = (g
Data
.lVal>>8)&0xff; buffer[m++] = g
Data
.lVal&0xff; } } else//long = char*1 //数据可能溢出 { buffer = new char[g
Data
Length]; for(m=0,n=0; n
DataLength; n++) { SafeArrayGetElement(
Data
.parray,&n,&g
Data
.lVal); buffer[n] = (char)g
Data
.lVal; } } break; case VT_ARRAY|VT_INT://以整型
数组
发
送 g
Data
.vt = VT_INT; if(g
Data
Type != 0) { //一个int等于四个char buffer = new char[g
Data
Length]; for(m=0,n=0; n>24)&0xff; buffer[m++] = (g
Data
.intVal>>16)&0xff; buffer[m++] = (g
Data
.intVal>>8)&0xff; buffer[m++] = g
Data
.intVal&0xff; } } else { buffer = new char[g
Data
Length]; for(n=0; n
DataLength; n++) { SafeArrayGetElement(
Data
.parray,&n,&g
Data
.intVal); buffer[n] = (char)g
Data
.intVal; } } break; case VT_ARRAY|VT_UI1://以BYTE
数组
发
送 g
Data
.vt = VT_UI1;//一个char等于一个BYTE不必进行转换 buffer = new char[g
Data
Length]; for(n=0; n
DataLength; n++) { SafeArrayGetElement(
Data
.parray,&n,&g
Data
.bVal); buffer[n] = g
Data
.bVal; } break; default://在这里没有一一列出其它类型,剩下的就由阁下进行数据转换处理了,我就偷懒了^_^ return -3;//传入的数据类型不被支持 } len =
send
(OnlySock, buffer, g
Data
Length, 0);//
发
送数据 delete[] buffer; buffer = NULL; if (len>24)&0xff; buffer[1] = (l
Data
>>16)&0xff; buffer[2] = (l
Data
>>8)&0xff; buffer[3] = l
Data
&0xff; //4个char组成一个long l
Data
_2 = ((buffer[0]&0xff)<<24) + ((buffer[1]&0xff)<<16) + ((buffer[2]&0xff)<<8) + (buffer[3]&0xff); 四、现在来看看Get
Data
()的处理,具体实现,请看如下代码: // TODO: Add your dispatch handler code here if(!OnlySock) return -1;//网络尚未开始建立连接 int g
Data
Type = VariantToLong(
Data
Type); long g
Data
MaxLength = VariantToLong(
Data
MaxLength); int gTimeOut = VariantToLong(TimeOut); if(g
Data
Type < 0) return -2; if(g
Data
MaxLength <= 0) return -2; if(gTimeOut < 0) return -2; switch(g
Data
Type) { case 0://默认形式,这时如果
发
现
Data
为整型
数组
,将不进行任何转换,直接把一个int传给一个char传送(数据可能溢出范围) case 1://当指定该值为1时,当Date为长整型
数组
时,将把一个long转换成四个char传送 case 2://当指定该值为2时,当Date为整型
数组
时,将把一个int转换成四个char传送 case 3://当指定该值为3时,当Date为无符号短整型
数组
时,将把一个unsigned short转换成两个char传送 case 4://当指定该值为4时,当Date为BYTE
数组
时,将把一个BYTE转换成一个char传送 case 5://当指定该值为5时,当Date为短整型
数组
时,将把一个short转换成两个char传送 case 6://当指定该值为6时,当Date为浮点型
数组
时,将把一个float转换成四个char传送 case 7://当指定该值为7时,当Date为双精度
数组
时,将把一个double转换成八个char传送 break; default://如果不在上面取值范围内,将按当前的
Data
相应类型进行传送 break; } timeval tv; fd_set fdread; int len = -3;//如果找不到该连接,则返回-3 long n = 0; long m = 0; long changetype = 0; VARIANT g
Data
; VariantInit(&g
Data
); char *buffer=NULL; buffer = new char[g
Data
MaxLength+1]; memset(buffer, 0, g
Data
MaxLength+1); FD_ZERO(&fdread); tv.tv_sec = gTimeOut;//超过指定时间后返回 tv.tv_usec = 0; FD_SET(OnlySock,&fdread);//是否可以读取数据 select( 0,&fdread,NULL,NULL,&tv); if(FD_ISSET(OnlySock,&fdread)) { len = recv(OnlySock, buffer, g
Data
MaxLength, 0); if (len<=0) { delete[] buffer; return -
10
2;//无法读取数据,对方可能已断开连接 } if(lenvt) { case VT_BSTR://按字符串形式接收 buffer[g
Data
MaxLength] = '\0';
Data
->bstrVal = _com_util::ConvertStringToBSTR(buffer); break; case VT_BYREF|VT_UI1: //按BYTE*形式接收 memcpy(
Data
->pbVal,buffer,g
Data
MaxLength); break; case VT_BYREF|VT_I1://按 char * 形式接收 memcpy(
Data
->pcVal,buffer,g
Data
MaxLength); break; case VT_BYREF|VT_I4://以长整型指针接收 buffer[g
Data
MaxLength]='\0'; for(n=0; nplVal[n] = buffer[n]; } break; case VT_ARRAY|VT_I4://以长整型
数组
接收 g
Data
.vt = VT_I4; if(g
Data
Type != 0) { for(m=0,n=0; n
DataMaxLength;n++) { g
Data
.lVal = ((buffer[m]&0xff)<<24) + ((buffer[m+1]&0xff)<<16) + ((buffer[m+2]&0xff)
Data.lVal); m = m+4; } } else { for(n = 0; nparray,&n,&g
Data
.lVal); } } break; case VT_ARRAY|VT_INT://以整型
数组
接收 g
Data
.vt = VT_INT; if(g
Data
Type != 0) { for(m=0,n=0; n
DataMaxLength;n++) { g
Data
.intVal = ((buffer[m]&0xff)<<24) + ((buffer[m+1]&0xff)<<16) + ((buffer[m+2]&0xff)
Data.intVal); m = m+4; } } else { for(n = 0; nparray,&n,&g
Data
.intVal); } } break; case VT_ARRAY|VT_UI1://以BYTE
数组
接收 g
Data
.vt = VT_UI1; for(n = 0; nparray,&n,&g
Data
.bVal); } break; default://其它类型,请各位看官自行实现处理,嘿嘿 delete[] buffer; return -3;//无法识别传入的数据类型 } } else { delete[] buffer; return 0;//网络数据读取超时 } VariantClear(&g
Data
); delete[] buffer; return len; 五、接下来,我们看看VC和VB如何调用该控件: VC调用控件方式: 新建一对话框工程,然后在工程中添加该控件,设置如下图: 图一 创建新对话框工程,并加入控件 响应控件的断网和数据到达事件,设置如下图: 图二 响应控件的两个事件 添加相应代码,看起来如下: void CTestMFC
WinSock
Dlg::OnRecvSockEventMfc
winsock
ctrl1() { // TODO: Add your control notification handler code here SAFEARRAYBOUND Bound[1];//一维
数组
Bound[0].lLbound=0; Bound[0].cElements=
10
0;//该一维
数组
最大接收
10
0个元素 VARIANT *
data
;
data
= new VARIANT; VariantInit(
data
);
data
->vt = VT_ARRAY|VT_I4;//指明为长整型
数组
data
->parray = SafeArrayCreate(VT_I4,1,Bound);//创建SAFEARRAY结构 long l = m_sock.Get
Data
(
data
, COleVariant((long)0), COleVariant((long)
10
0), COleVariant((long)3)); if(l<=0) { ;//在这里判断出错信息,并作相应处理,我就偷懒了. } char p
Data
[
10
0]={0};//这里以字符
数组
显示结果 long change = 0; for(long n=0; nparray,&n,&change); p
Data
[n] = (char)change; } CString mess; mess.Format("%s",p
Data
); AfxMessageBox(mess); SafeArrayDestroy(
data
->parray); delete
data
; } void CTestMFC
WinSock
Dlg::OnClose
Winsock
Mfc
winsock
ctrl1() { // TODO: Add your control notification handler code here m_sock.DisConnect();//调用断开连接接口 AfxMessageBox("服务器断开了该次连接,请检查!"); } void CTestMFC
WinSock
Dlg::OnConnect() { // TODO: Add your control notification handler code here Update
Data
(TRUE); if(!m_sock.Connect(COleVariant(m_ip),COleVariant(m_port))) AfxMessageBox("与服务器建立连接失败,请确认服务器是否存在!"); } VB调用控件方式: VB时面调用要方便很多,这得益于VB的很多自动化功能,请看下图: 图三 VB调用控件方法 同样,双击我们的控件,然后添加控件事件,如下图: 图四 VB响应控件事件 然后,添加相关代码如下: Private Sub Command1_Click() MFC
WinSock
1.Connect CStr(ip), CLng(port) End Sub Private Sub Command2_Click() MFC
WinSock
1.
Send
Data
"
Send
Data
: 欢迎使用!", 0, 50, 3 End Sub Private Sub MFC
WinSock
1_Close
Winsock
() MFC
WinSock
1.DisConnect MsgBox "服务器断开了连接,请检查!" End Sub Private Sub MFC
WinSock
1_RecvSockEvent() Dim
data
As Variant Dim
data
2(
10
0) As Long Dim
data
3 As String Dim l As Long
data
=
data
2 '在VB里当把一个Variant变量
data
等于另一个确定变量
data
2时,
data
将被初始化为与
data
2相同的类型变量 '
data
=
data
3 '如果让
data
等于
data
3,那么
data
将变成字符串型的变量参数 l = MFC
WinSock
1.Get
Data
(
data
, 0,
10
0, 3) '这时
data
里面已存放了接收到的数据
data
3 =
data
(0) '这里只显示接收到的首字符编码 MsgBox
data
3 End Sub 大家可以看到,对于SAFEARRAY类型的数据进行相关处理也并不可怕,由于在源码里给出了具体代码和详细注解,在这里我就不再赘述了, 至于BSTR和char *类型的数据,相信不用我多说,大家也已经知道如何使用了。 结束语: 全文至此暂告一段落,本文向大家展示了MFC ActiveX控件的魅力,以及所用的VARIANT类型参数,还详细给出了
WinSock
的开
发
代码, 以用在VC,VB的调用方法,由于这段时间忙于一些新项目的开
发
,因此没办法花太多时间进行详细解释,所以很多地方都直接给出源代码 再加上注解,而没有进行通俗的讲解,还请各位读者仔细查看源代码。 本控件目前只能作为客户端,阁下还可以继续进行完善,比如进行端口的监听,实现服务器的相关处理等等,但这已经不是本文的目的, 授人以鱼,不如授人如渔,剩下的功能,就由各位读者去实现了,也欢迎与我进行交流,谢谢! 另外:本文的示例,需要一个服务器程序,大家可以在网上随便下载一下进行测试,我就不提供了。 声明: 部分资料来源于网络,本文所用的所有源代码仅供非商业用途,并请保留原版权,否则后果自负! 欢迎大家拍砖,指正错误或不足的地方,一起探导更好的方法。 欢迎访问www.59186618.com,感谢您的支持!
VB中使用
WinSock
控件传送文件
传送文件对于网络编程来说是基本的功能,比如远程控制软件。在编制一个软件时,我从网上下了很多传文件的程序,这些程序提供的传文件功能根本就不能用。传文本还可以,传二进制文件根本就不行。因此,作为一个基本的功能模块,有必要单独介绍一下。 首先,在VB中要传送字符串,你可以这样写:Dim str
Data
As Stringstr
Data
= "Test"
Winsock
1.
Send
Data
strDa
Socket编程系列之2:Windows-API网络编程入门实战
Socket编程系列初步计划:Socket编程系列之1: Linux-API 网络编程入门实战Socket编程系列之2: Windows-API 网络编程入门实战Socket编程系列之3: Muduo 网络编程入门实战Socket编程系列之4: Libevent 网络编程入门实战Socket编程系列之5: Libcurl 网络编程入门实战Socket编程系列之6: Boost-ASIO 网络编程入门实战----------------------------------------------------Socket编程系列之2:Windows-API网络编程入门实战l
Winsock
编程接口l UDP程序设计l TCP套接口函数l Web客户/服务器程序l 基于windows的IO复用机制l UDP广播和多播l 套接字选项l Windows套接字I/O模型l 原始套接字与ICMPl WinInet简介与案例实战
VB6 通过
winsock
控件
数组
实现客户端和服务器多对一通信
VB6 通过
winsock
控件
数组
实现客户端和服务器多对一通信 注意:本文转载自http://blog.csdn.net/geohuskyer/article/details/626
10
62 说明:我是在最近开
发
一个考试
系统
过程中搜索到上面文章的,它提供的思想非常实用。当然,这篇文章仅提供了一个基本思路,详细的实现在人民邮电出版社出版的《Visual B...
winsock
使用
一,
Winsock
的属性1.
Winsock
1.localIP获得本机的ip地址2.
Winsock
1.RemoveHostIP获得客户机的ip3.
Winsock
:BytesReceived属性(接受数据的
字节
数),4.LocalHostName属性(本地主机名)5,LocalP 本
VB基础类
7,763
社区成员
197,609
社区内容
发帖
与我相关
我的任务
VB基础类
VB 基础类
复制链接
扫一扫
分享
社区描述
VB 基础类
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章