这次增加了与引擎的通信模块,这主要是为了使引擎和界面保持独立,在调试时不会相互影响。现在暂时不考虑界面怎么加载引擎的过程,启动时界面和引擎分别打开。
通信使用的是socket通信方式,为了简单起见,采用UDP无连接的通信方式。目前界面和引擎在同一台电脑上,IP地址使用的是都是本机回送地址127.0.0.1,界面的端口号是1234,引擎的端口号是5678。
创建socket时分为本地socket和目的socket,本地socket用来监听是否收到数据,目的socket用来向引擎发送数据
local.sin_family = AF_INET;
local.sin_addr.s_addr=INADDR_ANY;
local.sin_port = htons(1234);
if(bind(socket_fd, (struct sockaddr *)&local, sizeof(struct sockaddr) )<0)
{
printf("Bind Error!\n");
pthread_detach(pthread_self());
}
addr.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);
addr.sin_port = htons(5678);
pJunqi->socket_fd = socket_fd;
pJunqi->addr = addr;
socket通信运行在一个单独的线程里,一直监听引擎发过来的数据并进行处理。
void CreatCommThread(Junqi* pJunqi)
{
pthread_t tidp;
pthread_create(&tidp,NULL,(void*)comm_thread,pJunqi);
}
while(1)
{
recvbytes=recvfrom(socket_fd, buf, 100, 0,NULL ,NULL);
(void)recvbytes;//暂时不用,消除告警
DealRecData(pJunqi, buf);
}
通信报文由头部和数据内容组成,头部总共有8个字节,格式如下:
偏移地址(字节) | 长度(字节) | 描述 |
0 | 4 | 固定标识符 |
4 | 1 | 方位 |
5 | 1 | 功能码 |
6 | 2 | 待定 |
typedef struct CommHeader
{
u8 aMagic[4];
u8 iDir;
u8 eFun;
u8 reserve[2];
}CommHeader;
前4个字节固定为0x57,0x04,0,0,第5个字节指定方位,用来表示是哪一家行棋或者是哪一家的布阵。功能码用来表示具体发送的事件,不同的功能码会有不同的数据报文内容,目前定义了以下功能码:
#define COMM_OK 0
#define COMM_ERROR 1
#define COMM_GO 2
#define COMM_MOVE 3
#define COMM_EVNET 4
#define COMM_START 5
#define COMM_READY 6
#define COMM_LINEUP 7
#define COMM_INIT 8
#define COMM_STOP 9
各功能码的意义如下:
- COMM_OK
代表收到数据或处理完毕,没有实际意义。 - COMM_ERROR
接收到非法数据,如不按规则的移动和布阵 - COMM_GO
当引擎长时间思考时,该指令让引擎立即出招,点击橙色的小按钮会发送该指令 - COMM_MOVE
代表每一步的行棋和比较结果,引擎向界面只发送棋子移动坐标,在每一次行棋后界面都会向引擎发送棋子的移动还有判定结果告诉引擎棋盘上的信息变化。该指令的数据格式如下:偏移地址(字节)
长度(字节)
描述
0
2
棋子移动前坐标
2
2
棋子移动后坐标
4
1
判决结果(移动、吃子、打兑、撞死)
5
1
用最低3位bit分别表示附加判决:
0:军旗被挖
1:移动方司令阵亡
2:目标方司令阵亡
6
2
移动方军旗坐标
8
2
目标方军旗坐标
- COMM_EVNET
除了棋子的移动,棋盘上还会发生一些其他的事件,如跳过和投降,超时也算跳过,在头部后的一个字节用来表示发生的事件,0表示跳过,1表示投降 - COMM_START
当点击开始按钮时会发送该指令表示开始行棋,这条指令没有数据内容,方位字节表示先手。 - COMM_READY
界面向引擎发送该指令表示socket已经启动,当前处于布阵状态,当引擎向界面发送该指令时,界面会给引擎发送上家和下家的初始布阵 - COMM_LINEUP
当对上一家和下一家调入布阵或者调整布阵时,界面会向引擎发送该指令,该指令紧跟着30字节表示布阵的内容,即5*6个格子(25个棋子+5个营)。 引擎向界面发送该指令表示设置布阵。 - COMM_INIT
当界面收到COMM_READY指令后,会发送该指令到引擎表示初始化布阵,数据格式如下偏移地址(字节)
长度(字节)
描述
0
4
4字节代表每个方位,置1表示收到这一家布阵
4~30*?
30*?
收到的布阵
- COMM_STOP
当界面暂停时会发送该指令,此时停止计时,此时点击继续会立即出招按钮来告诉引擎继续行棋。
通信的内容基本就这么多吧,以后开发引擎时如果有需要再增加,至此界面部分的开发工作也就告一段落了,接下来要开始开发引擎了,现在展示一下当前的界面效果吧
源代码地址: