社区
VB基础类
帖子详情
用Winsock1.SendData发10位长字节数组,系统在尾加0,如何不发该0?
lu888
2000-08-24 07:39:00
...全文
63
回复
打赏
收藏
用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
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中的
Winsock
编程
一.引言Socket原意为”插座”,用于计算机通信则代表一种点到点信息传输。早期用于Unix
系统
上的通信编程规范,通信双方由代表两点的”服务器”和”客户”组成,基于IP协议进行按照TCP或UDP规范进行信息交换。建立双方通信的过程即称建立一个”套接字(Socket)”,建立后利用得到的”套接字”进行各种信息的交流。随着Windows
系统
的流行,开始有人在原来的基础上移植到Windows平台上。微
VB基础类
7,763
社区成员
197,609
社区内容
发帖
与我相关
我的任务
VB基础类
VB 基础类
复制链接
扫一扫
分享
社区描述
VB 基础类
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章