c语言大作业,和同学合作,他写游戏,我负责通信,因为没有基础(但是想法很大胆。。。可能),现在他游戏用cpp写差不多了,我还不清楚socket伺服器(Windows下的)怎么开始怎么写,还有如何实现和游戏对接,如何将传入的信息输入游戏,ip地址的设置blabla。。。好迷啊。


csdn里好像有,我看过一些好像是这个socket,你搜一下c++tcp或udp的网路通信即可。

区域网不用管,有明确的内网ip和程序埠区域网中两台机器一定可以连上,广域网的话就是多一个埠映射并且使用公网ip和映射的埠就可以。

可以一台机器运行伺服器端,然后两台机器连接他,也可以一台机器是集成了最基本的本地程序的伺服器端,另一台安装客户端(就是伺服器机上的程序可以作为伺服器,也可以供用户游玩,数据直接用变数传递),还可以无伺服器,两个程序一样,都是收别人的数据,处理,然后发送自己的,不用一段程序统一管理数据,各顾各,有点像去中心化了。

简单说前两种是一样的,就是两个员工只管著跟用户和领导传话,领导负责判决和告诉员工怎么跟客户说,只是领导坐在自己的办公室还是坐在其中一个窗口上的区别,那个离领导近的员工不用跑了。后面那一种是两个人互通数据,采用同一个规则同时处理整个事件。


泻药

根据你目前的情况 建议你请这个同学吃几顿饭让他帮你写 你若有心 再请他吃几顿饭 让他教你(


边看视频边写代码,多思考多练习,加油


首先,你需要想好整体架构。是采用对等方式还是有中心伺服器的方式。对等方式就是两个app直接通信,这样方式的好处是简单,坏处也是简单。由于太简单,所以只能一对一,且只能在区域网中对战。对你现在的目标没有什么影响,但是,做软体一般要多看一步。有中心伺服器的方式就没有这个问题了。既可以区域网也可以互联网,还可以做成对战平台。好处很多。复杂度也大不少。这个假设你是采用中心伺服器的方式,毕竟这种是主流。

这个时候就有一个分工问题了。中心伺服器负责两个客户端的通信,信息交换;还负责历史信息的记录,比如对战历史;仲裁,比如谁胜利了等等。而客户端用来显示界面、做简单的规则判断,比如已经某个坐标已经有棋子就不允许再下棋子等等。

然后,你需要设计一套通信协议,把需要通信的细节确定出来再动手实现。举例如下:

1.登录

客户端发送消息给伺服器端,消息中包含用户名、密码、客户端的版本号等信息。

伺服器登录消息给客户端,消息中包含是否登录成功,如果不成功,什么错误,如果成功返回个句柄以及用户的基本信息等等。

一般通信消息采用json格式进行封装,在C语言中可以使用cJson来处理json。消息的具体内容应该是:

登录请求:

{
"function_id": 1,
"username": "test1",
"password": "test",
"client_version": "0.0.1",
}

注意:密码一般都会采用md5等不可逆加密。

登陆应答:

{
"resturn_code": 0,
"resturn_message": "登录成功",
"user_id": 1,
"nickname": "张三",
"user_level": 5,
"user_token": "asdasdoij;lkj"
}

2.获取用户列表

从伺服器用户的列表及基本信息。

请求:
{
"function_id": 2,
"user_token": "asdasdoij;lkj"
}
应答:
{
"resturn_code": 0,
"resturn_message": "获取信息成功",
"users": [
{
"user_id": 1,
"nickname": "张三",
"user_level": 5,
"online": true,
"is_in_war": false,
"war_history": [1, 2, 3, 4, 5, 7, 8]
},

{
"user_id": 2,
"nickname": "李四",
"user_level": 3,
"online": true,
"is_in_war": false,
"war_history": [1, 2, 6, 7, 8]
},

{
"user_id": 3,
"nickname": "王二",
"user_level": 1,
"online": false,
"is_in_war": false,
"war_history": [3, 4, 5, 6]
}
]
}

一次对战就是一个war。每个war有一个唯一的id。war_history里面保存的是改用户参与的对战历史记录。

2.获取对战详情

从伺服器获取某次对战的信息信息。

请求:

{
"function_id": 3,
"war_id": 1
}

应答:

{
"black_user_id": 1,
"white_user_id": 2,
"winner_user_id": 2,
"date_begin": "2020-12-18 10:44:32",
"date_end": "2020-12-18 10:48:32",
"points": [
{
"x": 0,
"y": 0,
"color": "black",
},
{
"x": 0,
"y": 1,
"color": "none",
},
{
"x": 0,
"y": 2,
"color": "white",
},
......
]
}

3.开启对战

客户端发送请求:
{
"function_id": 3,
"user_token": "asdasdoij;lkj",
"dest_user_id": 2
}
应答:
{
"resturn_code": 0,
"resturn_message": "接收到请求"
}
开战请求通知:
{
"function_id": 3.1,
"src_user_id": 1,
"dest_user_id": 2
}
应战结果通知:
{
"function_id": 3.2,
"war_id": 10,
"action_user_id": 1,
"black_user_id": 1,
"white_user_id": 2,
"points": [
{
"x": 0,
"y": 0,
"color": "none",
},
{
"x": 0,
"y": 1,
"color": "none",
},
{
"x": 0,
"y": 2,
"color": "none",
},
......
]
}

应战结果通知中:

action_user_id: 接下来下子的用户id。

black_user_id: 执黑子的用户id。

white_user_id: 执白子的用户id。

points:棋盘信息。

具体步骤:

1)客户端请求与某用户对战,

2)伺服器端并不直接应答,而是将对战请求转发给目标客户端

3)目标客户端根据自己的情况觉得是否应战,将结果发送给伺服器。

4)如果应战,伺服器为二者创建一个war,将war_id同时发送给对战双方,并记录到各种的历史记录中。

4.应战

应战客户端发送应战响应给伺服器端。

请求:
{
"function_id": 4,
"user_token": "asdasdoij;lkj",
"src_user_id": 2,
"allow_war": true
}
应答:
{
"resturn_code": 0,
"resturn_message": "接收到请求"
}

5.下子

请求:
{
"function_id": 5,
"user_token": "asdasdoij;lkj",
"war_id": 10,
"point": {
"x": 0,
"y": 1,
"color": "black"
}
}
应答:
{
"resturn_code": 0,
"resturn_message": "下子成功"
}
下子结果通知:
{
"function_id": 5.1,
"war_id": 10,
"is_finished": false,
"winner_user_id": -1,
"action_user_id": 2,
"points": [
{
"x": 0,
"y": 0,
"color": "none",
},
{
"x": 0,
"y": 1,
"color": "black",
},
{
"x": 0,
"y": 2,
"color": "none",
},
......
]
}

具体步骤:

1)、某客户端发送下子请求

2)、伺服器端接收到请求后,判断各种条件是否满足,是否允许下子。如果允许下子,就判断下子后游戏是否结束,如果某人赢了也就结束了。否则,接下来该哪个用户下子了。同时,保存对战信息。

3)、最后将下子的结果发送给对战双方,对战双方接到消息后根据结果刷新棋盘界面。

如果想简单,还可以把历史对战信息去掉。想要更加完善,还可以把每次下子的信息记录下来,以便复盘,还可以实现中断和恢复对战功能。

有了框架和协议,接下来就是技术选型了。采用什么进行通信呢。最容易想到的当然是socket,采用TCP协议了。但是,如果采用这个比较容易陷入通信的细节之中。所以,建议采用zmq这种成熟的组件。zmq是消息队列组件。它对tcp协议做了封装,非常适合各种消息通信。比如,

a、登陆、获取信息和请求对战等等,都可以采用zmq的应答模式,客户端发请求,伺服器应答。

b、请求对战结果、下子结果等等可以采用管道模式,由伺服器把信息推给客户端。也可以采用订阅模式,将信息广播给客户端。如果采用订阅模式,还可以很方便的实现「观战」功能。对于观战者,只需要订阅对战的消息就可以了。

最后,就是动手实现了。这个部分就不多说了,简单讲一下基本流程吧。

客户端:

  1. 客户端连接伺服器端,ip地址肯定是用户提供的,可以通过配置文件或者某个控制项获取到伺服器ip地址,当然,也可以通过启动参数。
  2. 客户端获取伺服器端的用户列表,将在线的客户端列出来供用户选择,同时等待对战请求消息。
  3. 对于请求方:用户选择某用户后,客户端给伺服器端发送请求对战的消息。对于应战方,接收到请求后询问用户是否应战,然后向伺服器发送应战结果。
  4. 当客户端接收到对战结果通知后进入对战界面,并绘制棋盘
  5. 用户操作界面进行下子,客户端判断是否符合基本规则,符合规则,发送下子请求给伺服器端。
  6. 当客户端接收到下子结果通知后进入刷新棋盘,如果未结束等待下子,如果结束显示对战结果,并退出对战界面。

伺服器端:

1.等待客户端的请求,根据function_id处理对应的请求。

2.如果是登陆请求,检查密码是否正确....然后发送登陆结果给客户端。

3.如果是对战请求,将请求通过管道模式或者广播模式,发送给目标客户端。

......


啥不好用,非得用C/C++。

这个功能放到别的语言里顶多就是一百来行函数。

现在你得从底层一路撸到顶,这是一个从业几年的程序员都不太敢轻易尝试的东西。

这里面包含了:I/O模型、阻塞、多线程、TCP/IP、Win32程序设计等等。再加上C++本身的复杂程度,啧啧啧~

要能换语言就尽快换语言,实在不行建议上MFC,也是C++,但好歹很多东西都帮你写好了,直接用就行。


不要搞得太复杂。

复杂的后面再说,简单的先来


说说我的思路:

首先,通过万能的互联网搭建一个区域网的小网站。

这里可以用到Windows的服务(好像叫 IIS )

这时,有一个文件夹里的内容,可以在区域网上,通过一个ip地址(路由器分配给这个文件夹所在的设备的ip地址)访问

然后是简单粗暴的设计,通过定时扫描文件夹里的文件,反复上传下载里面的文件,即可实现数据的简单交互。


推荐阅读:
相关文章