quake3 源码分析(六)
--网络数据传输与接收
数据结构: #define MAX_LOOPBACK 16 typedef struct { byte data[MAX_PACKETLEN];// MAX_PACKETLEN = 1400 int datalen; } loopmsg_t; typedef struct { loopmsg_t msgs[MAX_LOOPBACK]; int get, send;//循环队列,指示接收或发送消息的位置 } loopback_t; loopback_t loopbacks[2];//使用两个队列:一个客户端用,一个服务器端用 //接收本地数据 qboolean NET_GetLoopPacket (netsrc_t sock, netadr_t *net_from, msg_t *net_message) { loop = &loopbacks[sock];// NS_CLIENT = 0,NS_SERVER = 1 if (loop->send - loop->get > MAX_LOOPBACK) loop->get = loop->send - MAX_LOOPBACK; if (loop->get >= loop->send) return qfalse; i = loop->get & (MAX_LOOPBACK-1); loop->get++; Com_Memcpy (net_message->data, loop->msgs[i].data, loop->msgs[i].datalen);//拷贝数据到缓冲 net_message->cursize = loop->msgs[i].datalen; Com_Memset (net_from, 0, sizeof(*net_from)); net_from->type = NA_LOOPBACK; return qtrue; } //发送本地数据 void NET_SendLoopPacket (netsrc_t sock, int length, const void *data, netadr_t to) { loop = &loopbacks[sock^1]; i = loop->send & (MAX_LOOPBACK-1); loop->send++; Com_Memcpy (loop->msgs[i].data, data, length);//将数据拷贝到缓冲队列 loop->msgs[i].datalen = length; } //发送网络数据 void Sys_SendPacket( int length, const void *data, netadr_t to ) { //根据发送数据的类型进行网络地址到SOCEKT地址的传换 //调用sendto函数发送数据, if( usingSocks && to.type == NA_IP ) { socksBuf[0] = 0; // reserved socksBuf[1] = 0; socksBuf[2] = 0; // fragment (not fragmented) socksBuf[3] = 1; // address type: IPV4 *(int *)&socksBuf[4] = ((struct sockaddr_in *)&addr)->sin_addr.s_addr; *(short *)&socksBuf[8] = ((struct sockaddr_in *)&addr)->sin_port; memcpy( &socksBuf[10], data, length ); ret = sendto( net_socket, socksBuf, length+10, 0, &socksRelayAddr, sizeof(socksRelayAddr) ); } else { ret = sendto( net_socket, data, length, 0, &addr, sizeof(addr) ); } //进行出错处理 }
本文深入剖析了Quake3中的网络数据传输机制,详细介绍了循环队列在客户端与服务器间的数据交换过程,并展示了如何通过特定的数据结构实现本地数据包的发送与接收。
&spm=1001.2101.3001.5002&articleId=5750408&d=1&t=3&u=ea2451098e654d3eb644e5add23be8ee)
3034

被折叠的 条评论
为什么被折叠?



