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地址)訪問

然後是簡單粗暴的設計,通過定時掃描文件夾里的文件,反覆上傳下載裡面的文件,即可實現數據的簡單交互。


推薦閱讀:
相关文章