紧急:有关SOCKET程序如何将数据打包?
数据包格式要求如下:
字节长度 内容
1 起始符,为0xFE
2 包体长度
16 手机号码
n 包体(字符串)
如何将(例如:手机号码:13012345678,包体:ABCDE)打包发出?
str系列操作中'\0'很是麻烦,高手指点,不胜感谢!!!!!
问题点数:20、回复次数:32Top
1 楼snsins(初雪草)回复于 2002-03-29 11:35:59 得分 0
采用一个特定的自己的格式可以吗??比如
0xFE|5|13012345678|ABCDE|
Top
2 楼ququshb(忘求了)回复于 2002-03-29 11:38:11 得分 0
定义一个结构:
typedef struct _packet
{
char id;
int iIength;
char cPhone[16];
char cBody[255];
}packet;
packet m_packet;
ZeroMemory(&m_packet,sizeof(packet));
m_packet.id = 0xfe;
m_packet.iIength = 1+4+16+255;
CopyMemory(m_packet.cPhone,"13012345678",11);
CopyMemory(m_packet.cBody,"ABCDE",5);
发出
Top
3 楼axin_online(阿新在线)回复于 2002-03-29 13:32:44 得分 0
我试了一下楼上的,但对方还是不能得到正确结果?
是用socket.Send(&m_packet,m_packet.iLength);
不知怎么回事?Top
4 楼greenyard(greenyard)回复于 2002-03-29 14:00:02 得分 0
应该是socket.Send(&m_packet,sizeof(packet));Top
5 楼dash()回复于 2002-03-29 14:02:22 得分 0
你是用的tcp吧?try it:
int sended;
while(sended<sizeof(packet))
{
sended+=send(s,....)
}
接收方也同Top
6 楼florist2000(我爱susan)回复于 2002-03-29 14:03:10 得分 0
修改一下
定义一个结构:
typedef struct _packet
{
char id;
int iIength;
char cPhone[16];
char cBody[255];
}packet;
packet m_packet;
ZeroMemory(&m_packet,sizeof(packet));
m_packet.id = 0xfe;
m_packet.iIength = 1+4+16+255;//这句有错误,呵呵
m_packet.iLength=sizeof (m_packet)//因为第一个是char型的数据不是一个字节,存在字节对齐问题。
CopyMemory(m_packet.cPhone,"13012345678",11);
CopyMemory(m_packet.cBody,"ABCDE",5);
发出
socket.Send(&m_packet,sizeof(m_packet));
另外如果使用的是阻塞型套节字,那么发出的字节数不一定就刚好是数据长度。
Top
7 楼lianhuiyong(阳关故人)回复于 2002-03-29 14:03:11 得分 0
ququshb(忘求了) 说得不错,这种方法应该没有错的,在接收端采用同样的结构体就可以了.Top
8 楼axin_online(阿新在线)回复于 2002-03-29 14:36:41 得分 0
1)我使用的阻塞型套节字,多线程.
2)对端不可能也采用这样的结构.
3)协议中规定起始符为一字节,长度为2字节,那么在Win2000和Win98中实现
该结构有何区别?一字节我觉得应该用BYTE?
4)接收端使用*((Short)包头+偏移值)来求包体长度不知对否?
另,我有好多头疼的问题,哪位专家能否在QQ中详聊,我的QQ 是 95896000.Top
9 楼axin_online(阿新在线)回复于 2002-03-29 15:02:48 得分 0
对端的接收线程,请大虾指点迷津:
UINT RecvThread(LPVOID pParam)
{
RECVDATA *pRecv=(RECVDATA *)pParam;
int len=1;
int error=0;
char *pBody=NULL;
char *pHdr=NULL;
char tmp1[255];
char tmp2[1024];
while (TRUE)
{
int res;
pBody=NULL;
pHdr=new char[pRecv->hdrSz];
if ((res=pRecv->pSocket->CAsyncSocket::Receive(pHdr, pRecv->hdrSz))==SOCKET_ERROR)
error=::GetLastError();
else
len=res;
if (len==0 || error==WSAECONNRESET || error==WSAECONNABORTED) break;
if (!error && len && pRecv->bodyPos!=-1)
{
short bodyLen=*((short *)pHdr+pRecv->bodyPos);
pBody=new char[bodyLen];
if ((res=pRecv->pSocket->CAsyncSocket::Receive(pBody,bodyLen))==SOCKET_ERROR)
error=::GetLastError();
else
len+=res;
if (len==0 || error==WSAECONNRESET || error==WSAECONNABORTED) break;
}
pRecv->pQueue->Add(new CMyMsg(pHdr,pBody,len,error));
pRecv->pWnd->PostMessage(WM_NEW_MESSAGE);
}
//清理,防止内存泄露
delete []pHdr;
delete []pBody;
pRecv->pWnd->SendMessage(WM_DONE_MESSAGE,(WPARAM)pRecv->id,(LPARAM)error);
return 0;
}
Top
10 楼niewq(强强)回复于 2002-03-29 15:32:31 得分 0
你保证给分我给你指点。上述都不能解决你的问题!Top
11 楼niewq(强强)回复于 2002-03-29 15:36:03 得分 0
对端的接收线程就像儿童级程序!
Top
12 楼axin_online(阿新在线)回复于 2002-03-29 15:45:22 得分 0
请指教!我保证给分,不够在加.Top
13 楼niewq(强强)回复于 2002-03-29 16:20:51 得分 0
1、需要考虑断链重连。
2、接收端收到的包不可能都是完整包!处理方法,开一个缓冲区,有数据来就接在缓冲区后面,然后来判断数据包。
3、最好是Client端在出现断链后发起重连。Server端在一个连接断开后,接受新的连接。
4、结构定义{包头标志,固定字段等,消息长度,消息(不定长度)}
如果还搞不定,留下email地址!Top
14 楼axin_online(阿新在线)回复于 2002-03-29 16:33:02 得分 0
我主要想知道怎样将数据打包,发送至对方,
不知上面说的结构有没有问题?
因为要处理UniCode和MBCS及不同操作系统之间,还有字节顺序等,这是重点
至于断链重连,错误捕获等已实现,不便写出,就不必深究了.Top
15 楼devil97518(天使也会疯)回复于 2002-03-29 16:53:03 得分 20
一定要自己定义数据结构,基于c/s的两边数据结构都得相同,上述几位说得不错,我给你一个超时处理方法,注意两边的数据结构要相同,很简单的。
我是基于c++左的,,你可以参考,改为mfc的形式。
WSADATA wsd;
SOCKET cClient;
int ret;
struct sockaddr_in server;
hostent *host=NULL;
if(WSAStartup(MAKEWORD(2,0),&wsd)){return 0;}
cClient=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(cClient==INVALID_SOCKET){return 0;}
//set Recv and Send time out
int TimeOut=6000; //设置发送超时6秒
if(::setsockopt(cClient,SOL_SOCKET,SO_SNDTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR){
return 0;
}
TimeOut=6000;//设置接收超时6秒
if(::setsockopt(cClient,SOL_SOCKET,SO_RCVTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR){
return 0;
}
//设置非阻塞方式连接
unsigned long ul = 1;
ret = ioctlsocket(cClient, FIONBIO, (unsigned long*)&ul);
if(ret==SOCKET_ERROR)return 0;
//连接
server.sin_family = AF_INET;
server.sin_port = htons(25);
server.sin_addr .s_addr = inet_addr((LPCSTR)pSmtp);
if(server.sin_addr.s_addr == INADDR_NONE){return 0;}
connect(cClient,(const struct sockaddr *)&server,sizeof(server));
//select 模型,即设置超时
struct timeval timeout ;
fd_set r;
FD_ZERO(&r);
FD_SET(cClient, &r);
timeout.tv_sec = 15; //连接超时15秒
timeout.tv_usec =0;
ret = select(0, 0, &r, 0, &timeout);
if ( ret <= 0 )
{
::closesocket(cClient);
return 0;
}
//一般非锁定模式套接比较难控制,可以根据实际情况考虑 再设回阻塞模式
unsigned long ul1= 0 ;
ret = ioctlsocket(cClient, FIONBIO, (unsigned long*)&ul1);
if(ret==SOCKET_ERROR){
::closesocket (cClient);
return 0;
}Top
16 楼niewq(强强)回复于 2002-03-29 16:55:53 得分 0
那不要用结构了,以字节为单位,开始几个字节(例如8个等)意义定义,在8个字节里面,说明后面数据的长度,接收端在收到后,怎么处理都行。Top
17 楼niewq(强强)回复于 2002-03-29 16:59:05 得分 0
很容易啊,自己试一下就都知道了嘛!Top
18 楼axin_online(阿新在线)回复于 2002-03-29 17:12:27 得分 0
强强:用结构做发送出去的字节序列和你说的方法是一样的,哪个更方便呢?
天使也会疯:谢谢!但在Win2000(UniCode)下如何设定一个字节呢?Top
19 楼niewq(强强)回复于 2002-03-30 09:16:03 得分 0
不要用结构,用结构的兼容性差,而且一旦出错将是崩溃型的。用字节来处理!即使有错,则错一、二条消息而已。Top
20 楼niewq(强强)回复于 2002-03-30 09:24:17 得分 0
建议所有字节都用两个字节来表示,在非Unicode的地方与Unicode的地方处理不同就行了!Top
21 楼kissfire(kissfire)回复于 2002-03-30 13:13:42 得分 0
signTop
22 楼dxhdxh2k(dxhdxh)回复于 2002-03-31 08:55:35 得分 0
upTop
23 楼iiii(甲天下汤圆)回复于 2002-03-31 20:54:01 得分 0
upTop
24 楼axin_online(阿新在线)回复于 2002-04-01 09:29:31 得分 0
各位继续发表高见Top
25 楼maxsuy(魔法兔子)回复于 2002-04-01 10:07:07 得分 0
我觉得你的程序存在相当大的资源浪费
如果数据体只有一个字节,也要发送300个字节的数据?
我的QQ525931,
EMAIL,cnredmay@163.comTop
26 楼axin_online(阿新在线)回复于 2002-04-01 10:22:46 得分 0
发送问题很好解决,定义该结构,但发送字节数按实际填写Top
27 楼it_wsp(挖掘者)回复于 2002-04-01 11:43:01 得分 0
很好的问题,我来倾听大家的高见了!
Top
28 楼knl(小K)回复于 2002-04-01 11:57:19 得分 0
真实高见!Top
29 楼Ask100()回复于 2002-04-01 23:44:26 得分 0
关注Top
30 楼daryl715(上善若水)回复于 2002-04-02 00:03:21 得分 0
关注Top
31 楼Developerljm(飞车)回复于 2002-04-02 17:01:19 得分 0
一群疯子,这么简单、简单的问题,用得着这么大动干戈吗???Top
32 楼jet_u()回复于 2002-04-02 17:06:27 得分 0
跟我遇到的问题有相似处Top
33 楼snsins(初雪草)回复于 2002-04-02 18:01:55 得分 0
根本就不要用到字节和结构!
其实很简单的问题
就按照我开始说的 那样,采用|来分割,以|结束一个包
收到后只要按照|来分解包就OK了
0xFE|5|13012345678|ABCDE|
Top




