ServerSocket和ClientSocket发自定义信息问题?

kingeboy 2005-10-10 06:12:09
RT,客户端和服务器通信比如有些自定义的消息应该怎么来设计呢?
简单的我知道可以用字符串,然后在字符串中添入有规则的代码,比如String strMsg="T,测试信息",就可以定义此条数据是一条文本信息;接收到数据后把相应的字段提取出来,判断第一个字符的内容进行相应的处理就行了.
但是如果程序中的自定义消息结构比较复杂,其中包含多种数据类型,刚才的方法好像就不太好用了,如果程序通信需要发送包含很多类型结构信息的数据,那该用什么方法比较好,或者应该怎么样去处理数据进行打包才好呢?
...全文
1323 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
justonmyway 2005-12-04
  • 打赏
  • 举报
回复
如果发送发发送成功一个包头后,发送数据体失败了.今多次重复发送都失败了最后放弃发送.
过断时间后发送方进行下一次新的数据的发送.
这时接收方,讲把第二次的包头和部分数据当做第一次的数据体.请问这种情况该如何处理.
zsp5869999 2005-10-14
  • 打赏
  • 举报
回复
www.51merit.com
上有

WINSOCK LAN传文件(倚天篇)
WINSOCK史上最经典的例子(屠龙篇)
的源代码!
qq:42872272

同样,还有高速缓存,内存数据库的做法!
netsys2 2005-10-12
  • 打赏
  • 举报
回复
void __fastcall TFrmMain::ServerClientRead(TObject *Sender,
TCustomWinSocket *Socket)
{
}

每个传入的Socket都是针对特定的连接,不同的客户连接后传输数据时用的
TCustomWinSocket *Socket不一样!

虽然读的事件是相同的,但读取数据时是通过Scoekt->ReceiveBuf来做的,
而不同的连接的SOCKET是不同的!
kingeboy 2005-10-12
  • 打赏
  • 举报
回复
再次感谢你的热情回复,还有点问题^_^!

>>如果有多个客户端向服务器发送数据,应该怎么处理啊。
>>一样的啊!不同的客户端建立不同的SOCKET,不会混淆的

建立了不同的SOCKET是不错,但是服务器端都是用同一个函数ServerSocket的OnClientRead方法来处理收到的数据的,这样不就有混淆了吗,是不是要用到多线程,那该怎么搞呢?
netsys2 2005-10-12
  • 打赏
  • 举报
回复
如果有多个客户端向服务器发送数据,应该怎么处理啊。

---->一样的啊!不同的客户端建立不同的SOCKET,不会混淆的

还有就是用你的这种方法在C语言的程序里面打的包,不知到在不同语言里面处理数据方不方便(如VB,Delphi)?
---》没有区别!
shadowstar 2005-10-12
  • 打赏
  • 举报
回复
netsys2(来电!)
真是热心,令人敬佩!

kingeboy 2005-10-12
  • 打赏
  • 举报
回复
我要设计的服务器不是很麻烦,只是起到一个集中管理和处理简单操作的作用,客户端连接到服务器后,客户端的某些操作要向服务器进行询问,比如查询某些关于本终端在服务器端记载的数据信息,然后服务器会返回对于请求终端相应的数据,当然在服务器端也可以很方便的向某个终端发送某些命令让终端处理,客户端每次发送的数据量可能不多,但次数有点频繁.
按你说的,我要在服务器端监视到有用户成功连接后,就在链表中添加包含此终端数据的XUser结构数据一项,等到再次接收到此终端的数据时就把收到的数据添入此终端的Buffer中,等待处理。
在终端断开连接后,根据判断终端的Socket,再将此终端在链表中的数据删除。
另外服务器端向某个终端发送数据,我现在是用遍历列表的方式来选择客户端进行发送的,程序段如下,有没有比较快捷的方法?
先记录了终端的Handle,然后遍历列表,跟据和服务器控件列表里面记载的连接Handle进行比较,判断是否是要发送的终端然后再给这个终端发信息
Handle hClientSocket;
for(int i=0;i<ServerSocket->Socket->ActiveConnections;i++)
{
if(ServerSocket->Socket->Connections[i]->Handle==hClientSocket)
{
SUT_MSG MsgBuf;
strcpy(MsgBuf.Buf,"服务器:測試信息!");
ServerSocket->Socket->Connections[i]->SendBuf(&MsgBuf,sizeof(MsgBuf));
break;
}
}
netsys2 2005-10-12
  • 打赏
  • 举报
回复
你需要对每个用户进行管理,你需要创建一个新的结构:

struct XUser
{
TCustomWinSocket *Socket;//记录每个用户的SOCKET,返回处理信息时可以
//用这个Socket来发送
BYTE *buf; //记录数据,应该申请比较大的缓冲,例如可装
//下3个完整的数据包
int bufindex; //当前BUF使用的位置
}

每收到一个数据,判断属于那个用户的(根据Socket比较),然后填入到该用户
的buf中(从 bufindex开始填)。

另外一个线程处理这些缓冲的数据,如果发现某用户的数据已经形成一个完整的
数据包,则立即处理,并移动bufindex和剩下的数据(也可用双链表指针)。
(如果业务量不大,不开线程,用timer来巡检也可)。


服务器的设计是一个非常困难的东西,你的基础较差,先做一个小的测试吧。

真正7*24的SERVER要求非常严格,在“专题开发”--》“网络通信”中,曾经有过讨论。


-----

顺便说一句,本题结题后,建议你提交为FAQ。
kingeboy 2005-10-12
  • 打赏
  • 举报
回复
>>虽然读的事件是相同的,但读取数据时是通过Scoekt->ReceiveBuf来做的,而不同的连接的SOCKET是不同的!

这个我知道了,但是你前面说的

>>如果是变长包,里面的Data改为指针,发送时先发包头,然后发指针指向的数据。

那不是接收方要收到两次发送方发送的数据,当第一个客户端发送包头后,服务端等待接收客户1的第二次发送的数据,这时第二个客户端又发送数据过来,依次类推比如有n个客户发送给服务器端,那服务器怎么存储各个客户端发送的包头,从而按照各客户端先前发送的包头来处理客户端下一次发送的数据?
Lewolf 2005-10-11
  • 打赏
  • 举报
回复
这就是个协议的问题,如果对通讯效率要求高可能需要自定义二进制的通讯方式,比较麻烦,如果不够高的话,可以使用Http、Mime、Xml等高层协议,处理起来简单,而且同用性好一些。
kingeboy 2005-10-11
  • 打赏
  • 举报
回复
to: netsys2
谢谢大大的帮助,你的方法还是比较好用的。
如果像你说的
“如果是变长包,里面的Data改为指针,发送时先发包头,然后发指针指向的数据。”
--》》如果有多个客户端向服务器发送数据,应该怎么处理啊。
还有就是用你的这种方法在C语言的程序里面打的包,不知到在不同语言里面处理数据方不方便(如VB,Delphi)?
netsys2 2005-10-11
  • 打赏
  • 举报
回复
但是要把整形、浮点数、字符串转换成BYTE类型存入始终没有很方便的方法,

---->无所谓!

examples:

int i = 10;
float f = 20.12;
char *s="123";

char *data;//要new一段BUF后才能使用
int index=0;

memcpy(data+index,(BYTE*)&i,sizeof(int));//save int
index+=sizeof(int);

memcpy(data+index,(BYTE*)&f,sizeof(float));//save float
index+=sizeof(float);

memcpy(data+index,(BYTE*)s,strlen(s));//save string
index+=strlen(s);


读:


int i;
float f;
char s[100];

char *data;//读到的大块数据
int index=0;

memcpy((BYTE*)&i,data+index,sizeof(int));//read int
index+=sizeof(int);

memcpy((BYTE*)&f,data+index,sizeof(float));//read float
index+=sizeof(float);

strcpy((BYTE*)s,data+index);//read string


sxzqlzx 2005-10-11
  • 打赏
  • 举报
回复
定义一个结构发送吧,bcb6是不支持的,java支持,期待bcb10的出现
kingeboy 2005-10-11
  • 打赏
  • 举报
回复
多谢netsys2大大的赐教,小弟不胜感激,因为刚接触到网络编程所以对网络通信不是太熟悉,如果用你说的方法是可行,但如果我要发送的数据包含很多种类型数据信息,比如数值行、字符串形等要压入BYTE Data[1024]中会比较麻烦,以前用过类似的方法,但是要把整形、浮点数、字符串转换成BYTE类型存入始终没有很方便的方法,不知高人都用什么方法来把数据存入BYTE类型中的。
或者是有什么更好的存储数据的方法,希望CSDN的大大们不要吝啬来教教小弟吧。
netsys2 2005-10-11
  • 打赏
  • 举报
回复
接收到数据,然后察看其中的数据,字符数组中的数据完好,但Buf.pI的内容已不是发送方指针指向变量的数据.

----->肯定的,指针指向的是本机内存中某地址,而对方内存环境和本
机根本不一致,所以绝对不要直接传指针过去,一点用都没有!
直接传指针指向的数据。



我做通信系统十多年了,下面的经验你应该用得到:



---------------------------


一个通用的协议帧包括以下结构:

帧头(1-4 byte,判定是不是自己的数据)+命令头(1byte)+数据长度(2-4 byte)+ 效验(1-n byte )+保留(2)+数据

例如:


0F FF F0 F2 + A0 + 01 10 + 10 + 00 00 + 12 34 56 ...
----------- --- ------- ---- ----- ------------
帧头 命令 数据长度 效验 保留 数据

说明:
1)帧头:便于SERVER端分割处理多个包,唯一性表示每帧的起始位置
2)命令:有多少种交易、业务,就需要定义多少种命令
3)数据长度:后面的数据净荷长度,也可改为整包长度
4)效验:数据包是否完整的效验值,不一定要MD5,把全部数据包模二加的值放在这里也可以
5)保留:为未来发展保留
6)数据。。。




数据结构:

struct MyData{
DWORD FHead;
BYE Cmd;
WORD DataLen;
BYTE CRC;
BYTE Res[2];
BYTE Data[1024];
};

如果是变长包,里面的Data改为指针,发送时先发包头,然后发指针指向的数据。
为了快速,最好是申请一块大内存,然后自己填包,一次发送。
kingeboy 2005-10-11
  • 打赏
  • 举报
回复
to:shadowstar
我当然知道指针类型的意思了,只是不知道用TClientSocket的SendBuf方法能不能把指针类型变量的数据给发送出去。
如我用“sfengnet”的方法定义了一个结构Msg
struct Msg
{
char Buffer[256];
int *pI;
}
然后用这个结构定义变量
Msg sutMsg;
int i=10;
strcpy(sutMsg.Buffer,"信息!");
sutMsg.pI=i;
用SendBuf方法发送出去
ClientSocket->Socket->SendBuf(&sutMsg,sizeof(sutMsg));
当接收方用
Msg Buf;
Socket->ReceiveBuf(&Buf,Socket->ReceiveLength());
接收到数据,然后察看其中的数据,字符数组中的数据完好,但Buf.pI的内容已不是发送方指针指向变量的数据.
shadowstar 2005-10-11
  • 打赏
  • 举报
回复
楼主首先要把指针数据类型搞清楚。

打好基础。
kingeboy 2005-10-11
  • 打赏
  • 举报
回复
谢谢两位的回复,小弟没有搞过这么复杂的数据通信,能不能说一下具体该怎么打包发送和接收到数据后怎么提取数据?
我以前也定义过一些简单的Struct,如“sfengnet”写的那样,可以把数据赋值进去,然后发送,但是接收方收到数据再进行数据转换后有些指针类的数据会丢失,不知怎么回事?
sfengnet 2005-10-11
  • 打赏
  • 举报
回复
可以将你所需要握手的命令写在网络传输的自定义的数据报头中,对方收到后将命令提取出来进行相应的处理。

struct ExMsg{
char *Command; //命令
int64 DataSize; //数据大小
char *MD5Value; //MD5校验值
TTransData *Data; //数据
}

1,316

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder 网络及通讯开发
社区管理员
  • 网络及通讯开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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