(求助Delphi高手)delphi socket发送和接受tcp信息包

lengfeng884 2010-08-20 05:15:01
如题 控件用的是TSERVERSOCKET 和 TCLIENTSOCKET 刚开始直接传输字符串可以实现 后面改成传输消息包 要获取和传递包头信息就有点搞不来了 弄了一天没效果 希望高手帮忙写段代码或者给个样例 小弟感激不尽 http://blog.csdn.net/lengfeng847/archive/2010/08/20/5827141.aspx

内容在上面的连接博客 帮忙看下 谢谢!
...全文
1062 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
lengfeng884 2010-08-24
  • 打赏
  • 举报
回复
没人呢
lengfeng884 2010-08-23
  • 打赏
  • 举报
回复
谢谢lz
近有个项目用到delphi 以前学过 但是网络通讯这块不懂 以前是直接接受字符串现在改用传递信息包 希望大侠帮忙写下接受和发送特定信息包的代码

下面为信息包的格式和内容

数据包格式如下图所示,所包含的内容从左到右进行传输:包头中的信息全部为网络字节顺序!


序号
字段名称
长度(Bytes)
类型(C++)
字段说明

1
head
2
Unsigned Short
包头标识,固定为0xFFFF

2
version
2
Unsigned Short
版本信息,当前为0x0030

3
length
2
Unsigned Short
包括包头的全部包体长度

4
command
2
Unsigned Short
命令号

5
status
4
Unsigned Integer
应答状态

6
taskid
4
Unsigned Integer
任务流水号

7
sender
4
Unsigned Integer
发送方标识1

8
sessionid
4
Unsigned Integer
发送方标识2

9
timestamp
4
Unsigned Integer
时间戳

10
flag
2
Unsigned Short
数据加密标志:0:不加密,1:DES加密

11
reserved
4
Unsigned Integer
保留字段



包头信息中,开始标识(head),版本信息(version)为固定格式;

包体长度(length),提示整个包体(包括包头)的长度,接收方据此来完成一个业务数据包的接收和解析;

命令号(command),为客户端和服务器约定的业务命令,从0到65535,具体定义详见下表:

号码段
起始编号
结束编号
使用说明

1
0X0000
0X03E7
对应具体的业务命令号,如1为充值等

2
0X03E8
0XFFFF
系统保留命令字,目前0XFFFE为心跳包,0XFFFF为心跳应答包




应答状态(status),请求时总设置为0;应答时,由SP应用服务程序返回相应的操作结果或错误原因;

任务流水号(taskid)由自行定义,SP应用程序在响应包中必须返回,SP应用程序可以将此作为数据包一段时间内的唯一序列号。

发送方标识1(sender)、发送方标识2(sessionid)、时间戳(timestamp)以及保留字段(reserved),可以为发送方保留一些私有信息,返回包时原样返回。

包头信息中,除了包体长度(length)以外,其他的字段,包括开始标识(head),版本信息(version),任务流水号(taskid),发送方标识1(sender),发送方标识2(sessionid),时间戳(timestamp),以及数据加密标识(flag),需要在响应包中原样返回;
流程
1、 通用网关在连接建立之后,根据刚才加密的字节流,加上信息包头,组合成信息包,然后发送(Send)信息包,发送的字节数为加密后的字节流字节数+24(24信息包头的字节长度);在上述的例子中,信息包大约如ffff0200 00001100 00004e5f 00114b3f 00000000 0100 0038 2fd65329e2770074791503c2dab1d209fe0225636dd07f7277bd291209e1a498df28f7af2f0eb4f1be2831f0fa8987b7f9;其中业务加密字节流的长度这里是56,体现在网络字节中是0x0038,如果是x86系列的PC,需要做主机到网络(ntohs)字节顺序转换;

2、 SP应用服务程序接收(Recv)该信息包,根据包头信息截取对应的字节流,然后进行解密处理,得到加密前的业务字符串,另外还需要把其他的包头标识、两个包头保留字,存储在本地;

3、 SP应用服务程序根据流程开发人员与之协商好的格式对接收的字符串进行解析,然后进行响应的处理

4、 SP应用服务程序在发送之前,同样根据密匙对该返回字符串进行加密处理,然后对加密字节流长度进行计算,加上刚才发送过来的包头标识和版本号以及保留字等,组合成信息包;注意这时,字节流的长度是返回加密字节流的长度,而且是网络字节的

以下是自己接受字符串的时的代码


procedure TForm1.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
lmsg:String;
vflag,i,j:Integer;
larriveDate:TarriveDate;
ip:String;
islimit:Boolean;
resData:String;//返回数据
buff:array[0..255]of byte;
begin
ip:=Socket.RemoteAddress;
islimit:=True;
For j:=0 to ips.Count-1 Do
Begin
if (ip=ips[j]) then
begin
islimit:=False;
end;
End;
if not islimit then
Begin
CoInitialize(nil);
Socket.ReceiveBuf(buff,4);//应该就在这里修改吧
lmsg:=Socket.ReceiveText;
SendTo();
Memo1.Lines.Add(DateTimeTostr(now)+'来自主机'+ip+'的请求数据:'+lmsg );
saveToLog(DateTimeTostr(now)+'来自主机 '+ip+ ' 的请求数据:'+ lmsg);
if lmsg<>'' then
Begin
try
saveToLog(DateTimeTostr(now)+'开始处理接受数据'+lmsg);
larriveDate:=analyecmdData(lmsg);
vflag:=exChange(larriveDate);
Memo1.Lines.Add('*'+Socket.ReceiveText+'*'+lmsg);
Memo1.Lines.Add(DateTimeTostr(now)+'数据处理完毕:处理结果:'+inttostr(vflag));
saveToLog(DateTimeTostr(now)+'数据处理完毕:处理结果:'+inttostr(vflag));

except
begin
vflag:=1;
Memo1.Lines.Add(DateTimeTostr(now)+'数据处理异常:'+inttostr(vflag));
saveToLog(DateTimeTostr(now)+'数据处理异常:'+inttostr(vflag));
end;
//vflag:=1;
end;
for i:=0 to sessions do
begin //取得匹配的客户端
if session[i].CHandle = Socket.SocketHandle then
begin
case vflag of
0: resData:=inttostr(vflag)+'$'+larriveDate.userID+'$'+larriveDate.TelNo+'$'+inttostr(larriveDate.inPutKey);
1: resData:='1'+'$'+'系统繁忙请稍后冲值';
2: resData:='2'+'$'+'平台用户ID不存在';
end;

session[i].CSocket.SendText(resData);
Memo1.Lines.Add(DatetimeTostr(now)+'向客户端发送处理完毕命令'+resData);
saveToLog(DatetimeTostr(now)+'向客户端发送处理完毕命令'+resData);
end;
end;
end;
CoUninitialize;
end
else
Begin
CoInitialize(nil);
CoUninitialize;
// saveToLog(DatetimeTostr(now)+'非法访问Ip'+ip+'访问被阻止');
End;
end;
2个问题
1现在不会写的代码是如何获得信息包然后再按包头格式分析出包头和数据信息
2把处理后的数据加上以前的报头信息一起做应答处理
哪位帮忙看下 我把工程发你帮我完善下那部分代码 谢谢 我QQ419718285 你给个联系方式我联系你行
lengfeng884 2010-08-23
  • 打赏
  • 举报
回复
顶上去 急######
haitao 2010-08-22
  • 打赏
  • 举报
回复
字符串里可以包含二进制不可见字符的
kye_jufei 2010-08-22
  • 打赏
  • 举报
回复
網上很多類似實例,你參考下這一個貼子:http://hcqi2004.blog.163.com/blog/static/72682418200925112641385/
本例子就是Delphi中如何利用Socket编写通信程序。 计算机网络是由一系列网络通信协议组成的,其中的核心协议是传输层的TCP/IP和UDP协议。TCP是面向连接的,通信双方保持一条通路,好比目前的电话线,使用telnet登陆BBS,用的就是TCP协议;UDP是无连接的,通信双方都不保持对方的状态,浏览器访问Internet时使用的HTTP协议就是基于UDP协议的。TCP和UDP协议都非常复杂,尤其是TCP协议,为了保证网络传输的正确性和有效性,必须进行一系列复杂的纠错和排序等处理。   Socket是建立在传输层协议(主要是TCP和UDP)上的一种套接字规范,最初是由美国加州Berkley大学提出,它定义两台计算机间进行通信的规范(也是一种编程规范),如果说两台计算机是利用一个“通道“进行通信,那么这个“通道“的两端就是两个套接字。套接字屏蔽了底层通信软件和具体操作系统的差异,使得任何两台安装了TCP协议软件和实现了套接字规范的计算机之间的通信成为可能。   微软的Windows Socket规范(简称winsock)对Berkley的套接字规范进行了扩展,利用标准的Socket的方法,可以同任何平台上的Socket进行通信;利用其扩展,可以更有效地实现在Windows平台上计算机间的通信。在Delphi中,其底层的Socket也应该是Windows的SocketSocket减轻了编写计算机间通信软件的难度,但总的说来还是相当复杂的(这一点在后面具体会讲到);Inprise在Delphi中对Windows Socket进行了有效的封装,使得用户可以很方便地编写网络通信程序。 本例子就是Delphi中如何利用Socket编写通信程序。

1,593

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 网络通信/分布式开发
社区管理员
  • 网络通信/分布式开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧