我现在要给服务器端发送数据,包括包头和包体,包头包体格式定义如下:
通用数据包结构分为两部分,包头和包体:
包头控制信息:
编译时,结构体采用1byte对齐
struct PktCtlMsg
{
unsigned long len; //4 byte //包的总长度,包头加正文长度之和
unsigned char factorycode;//1 byte //厂商编码(保留)
unsigned char progid;//1 byte //进程号
unsigned char morepkt;//1 byte //是否还有后续包(保留)
char cmd_id[10];//10 byte //命令字,最大长度为9,不足位补空格
long start_num;//4 byte //起始记录号(保留)
long end_num;//4 byte //终止记录号(保留)
long request_id;//4 byte //请求号
long answer_id;//4 byte //应答号(保留)
long sequence;//4 byte //包序号
char link_user[9];//9 byte //连接的用户名(保留)
char link_pwd[9];//9 byte //连接的密码(保留)
short errorcode;//2 byte //返回码(保留)
}; 2) 协议包结构:编译时,结构体采用1byte对齐
struct PktMsg
{
struct PktCtlMsg CtlMsg; //包头控制信息
char datatrans[1]; //传送内容,从datatrans开始为协议正文,格式为XML文本};
现在我要传送的包体xml格式的数据为:
<?xml version="1.0" encoding="GB2312"?> <NewNSPasswordCompare AttrType="NewNSPasswordCompare" Verb="Retrieve"> <AreaCode AttrType="String">0931 </AreaCode> <CompareType AttrType="String">1 </CompareType> <ProuductType AttrType="String">1 </ProuductType> <Number AttrType="String">8788330 </Number> <CertificateType AttrType="String"> </CertificateType> <PassType AttrType="String">1 </PassType> <PassWord AttrType="String">000000 </PassWord> <PassCode AttrType="String">1 </PassCode> <Channel AttrType="String">web10000 </Channel> <StaffNo AttrType="String">web10000 </StaffNo> </NewNSPasswordCompare>
我现在要把这个数据传过去,我该怎么写啊?第一次做这个,不懂,望赐教
通用数据包结构分为两部分,包头和包体:
包头控制信息:
编译时,结构体采用1byte对齐
struct PktCtlMsg
{
unsigned long len; //4 byte //包的总长度,包头加正文长度之和
unsigned char factorycode;//1 byte //厂商编码(保留)
unsigned char progid;//1 byte //进程号
unsigned char morepkt;//1 byte //是否还有后续包(保留)
char cmd_id[10];//10 byte //命令字,最大长度为9,不足位补空格
long start_num;//4 byte //起始记录号(保留)
long end_num;//4 byte //终止记录号(保留)
long request_id;//4 byte //请求号
long answer_id;//4 byte //应答号(保留)
long sequence;//4 byte //包序号
char link_user[9];//9 byte //连接的用户名(保留)
char link_pwd[9];//9 byte //连接的密码(保留)
short errorcode;//2 byte //返回码(保留)
}; 2) 协议包结构:编译时,结构体采用1byte对齐
struct PktMsg
{
struct PktCtlMsg CtlMsg; //包头控制信息
char datatrans[1]; //传送内容,从datatrans开始为协议正文,格式为XML文本};
现在我要传送的包体xml格式的数据为:
<?xml version="1.0" encoding="GB2312"?> <NewNSPasswordCompare AttrType="NewNSPasswordCompare" Verb="Retrieve"> <AreaCode AttrType="String">0931 </AreaCode> <CompareType AttrType="String">1 </CompareType> <ProuductType AttrType="String">1 </ProuductType> <Number AttrType="String">8788330 </Number> <CertificateType AttrType="String"> </CertificateType> <PassType AttrType="String">1 </PassType> <PassWord AttrType="String">000000 </PassWord> <PassCode AttrType="String">1 </PassCode> <Channel AttrType="String">web10000 </Channel> <StaffNo AttrType="String">web10000 </StaffNo> </NewNSPasswordCompare>
我现在要把这个数据传过去,我该怎么写啊?第一次做这个,不懂,望赐教
因为socket应该就是基于TCP/IP了
他其实就是发送的二进制数据流
所谓包结构就是指一段完整数据流里的信息是怎样的
从多少字节到多少字节里存储的什么信息
不知道这样说能明白吗?
OutputStream.write(byte[])另外..
struct PktMsg
{
struct PktCtlMsg CtlMsg; //包头控制信息
char datatrans[1]; //传送内容,从datatrans开始为协议正文,格式为XML文本}; 正文长度 1??
我们在应用层通常不习惯使用这种晦涩的数据结构,所以在应用和后台之间架设了专门的统一数据平台,向应用统一提供XML结构的数据,后端可以是任意的第三方服务,当然也包括楼主说的这种格式的简单文本协议,而且是用的最多的!
单纯写个程序处理一个这样的交易,把定长格式转化为XML,没有太多技术难点,就是烦,而且极容易出错!
我的解决方案是自己写一个流程调度引擎,完全配置化地调度各个部件,实现这些转化过程,全过程都依赖XML的XPath,前端使用Web容器,提供HTTP协议的XML交换,也可以在负载均衡点前端加上一个自己写的代理(这个代理没有经过考验,压力上没什么信心)提供简单文本协议来交换XML数据!楼主说的这个问题,在整个解决方案中只是一个处理器,这个转化的过程估计楼主还漏了几点没说到:
1、每个字段的对齐方式;
2、每个字段在原始数据不足时(即占不满所有位时),用什么字符补齐;
转换过程一般会有两步,从XML中抽取相应字段填充到byte[]
中间有一个过程是直接拿这个byte[]与第三方服务器交换
交换到的byte[],再依照接口格式,从相应位置抽取出组成XML各个字段需要的数据!
通常转化过程还包括一些多行数据的问题
我不知道楼主做的东西是不是我说的这样,你提的问题应该是第一个转换过程,从XML中抽取相应字段填充到byte[]
不过我看楼主似乎从前是用的Unix C来实现的吧,其实主要的难点不在转换的过程,而是如何将整个过程配置化!一直以为自己做的这个东东很冷门,今天终于看到同道了,出来吼一吼!
以下是我的解决方案中,某个交易的这三个过程的配置,楼主可以参考一下:
<processor imp="processor.XMLToBytes" attach="CRequest">
<include src="/config/djk/public.xml/*/requesthead/*" />
<field length="6">500020</field>
<field name="CardNo" length="21" align="right" fix=" " ></field>
</processor>
<processor imp="processor.CSocket" request="CRequest" response="CResponse" reqHead="ReqHead" respHead="RespHead">
<include src="/config/djk/public.xml/*/port30012/server" />
</processor>
<processor imp="processor.BytesToXML" attach="CResponse">
<field name="SetAmt" length="17" ></field>
<field name="DefAmtV" length="17" ></field>
<rows name="Detail" size="Rec1">
<field name="BalCom" length="3" ></field>
<field name="OldCycIst" length="17" ></field>
</rows>
</processor>
对于PktMsg结构体对应的Java类,需要编写一个byte [] getBytes()方法,返回一个信息包的比特数组,
或者void write(Writer writer)方法,将该对象对应的byte数组写入IO流,
用于网络传输。PktMsg结构体当中char datatrans[1]; 可能有些不对,按我理解,应该是个char数组,也就是:char[] * datatrans ;至于PktMsg结构体对应的Java类当中, char datatrans[1];对应的成员变量,到底用什么来表示,
要看楼主的具体程序环境,如果使用什么Dom4j之类的,那就用Document的引用来做成员变量;当然,不反对其他类型的成员变量,
比如byte []类型,String类型,自定义的类型。具体怎样编码,协议里面应该都有明确的说明,查一查,就能搞定了。
public String toString()
{
//1.将所有字段的值组成一个字符串
//2.然后return这个字符串
}
以后只要new了这个bean对象,在set完所有的字段后直接调用toString方法就能得到所有字段组成的包头信息(可设置一个字符串(如strHead)存取)了!
2.将xml文本用输入流来读取,然后将其存入一个字符串中(比如:strInfo)3.将strHead与strInfo合并,存入到一个strMsg中。然后strMsg.getByte()得到的字节数组用socket方式发送出去即可!import java.net.*;
public class UdpSend
{
public static void main(String [] args) throws Exception
{
DatagramSocket ds=new DatagramSocket();
strMsg=strHead+strInfo;
DatagramPacket dp=new DatagramPacket(strMsg.getBytes(),strMsg.lengt(),InetAddress.getByName(服务器IP,端口号);
ds.send(dp);
ds.close();
}
}
//服务器IP,端口号 自己指定!!
注意参数之间的前后顺序和所占字节的大小
可以用ByteBuffer来存放所要传送的数据信息