P2P 涔?UDP絀塊廚AT鐨勫師鐞嗕笌瀹炵幇錛堥檮婧愪唬鐮侊級
鍘熷垱錛歴hootingstars
鍙傝冿細http://midcom-p2p.sourceforge.net/draft-ford-midcom-p2p-01.txt
璁哄潧涓婄粡甯告湁瀵筆2P鍘熺悊鐨勮璁猴紝浣嗘槸璁ㄨ褰掕璁猴紝寰堝皯鏈夊疄璐ㄧ殑涓滆タ浜х敓錛堟簮浠g爜錛夈傚懙鍛碉紝鍦ㄨ繖閲屾垜灝辯敤鑷繁瀹炵幇鐨勪竴涓簮浠g爜鏉ヨ鏄嶶DP絀胯秺NAT鐨勫師鐞嗐?/p>
棣栧厛鍏堜粙緇嶄竴浜涘熀鏈蹇碉細
聽聽聽 NAT(Network Address Translators)錛岀綉緇滃湴鍧杞崲錛氱綉緇滃湴鍧杞崲鏄湪IP鍦板潃鏃ョ泭緙轟箯鐨勬儏鍐典笅浜х敓鐨勶紝瀹冪殑涓昏鐩殑灝辨槸涓轟簡鑳藉鍦板潃閲嶇敤銆侼AT鍒嗕負涓ゅぇ綾伙紝鍩烘湰鐨凬AT鍜孨APT(Network Address/Port Translator)銆?br />聽聽聽 鏈寮濮婲AT鏄繍琛屽湪璺敱鍣ㄤ笂鐨勪竴涓姛鑳芥ā鍧椼?br />聽聽聽
聽聽聽 鏈鍏堟彁鍑虹殑鏄熀鏈殑NAT錛屽畠鐨勪駭鐢熷熀浜庡涓嬩簨瀹烇細涓涓鏈夌綉緇滐紙鍩燂級涓殑鑺傜偣涓彧鏈夊緢灝戠殑鑺傜偣闇瑕佷笌澶栫綉榪炴帴錛堝懙鍛碉紝榪欐槸鍦ㄤ笂涓栫邯90騫翠唬涓湡鎻愬嚭鐨勶級銆傞偅涔堣繖涓瓙緗戜腑鍏跺疄鍙湁灝戞暟鐨勮妭鐐歸渶瑕佸叏鐞冨敮涓鐨処P鍦板潃錛屽叾浠栫殑鑺傜偣鐨処P鍦板潃搴旇鏄彲浠ラ噸鐢ㄧ殑銆?br />聽聽聽 鍥犳錛屽熀鏈殑NAT瀹炵幇鐨勫姛鑳藉緢綆鍗曪紝鍦ㄥ瓙緗戝唴浣跨敤涓涓繚鐣欑殑IP瀛愮綉孌碉紝榪欎簺IP瀵瑰鏄笉鍙鐨勩傚瓙緗戝唴鍙湁灝戞暟涓浜汭P鍦板潃鍙互瀵瑰簲鍒扮湡姝e叏鐞冨敮涓鐨処P鍦板潃銆傚鏋滆繖浜涜妭鐐歸渶瑕佽闂閮ㄧ綉緇滐紝閭d箞鍩烘湰NAT灝辮礋璐e皢榪欎釜鑺傜偣鐨勫瓙緗戝唴IP杞寲涓轟竴涓叏鐞冨敮涓鐨処P鐒跺悗鍙戦佸嚭鍘匯?鍩烘湰鐨凬AT浼氭敼鍙業P鍖呬腑鐨勫師IP鍦板潃錛屼絾鏄笉浼氭敼鍙業P鍖呬腑鐨勭鍙?
聽聽聽 鍏充簬鍩烘湰鐨凬AT鍙互鍙傜湅RFC 1631
聽聽聽
聽聽聽 鍙﹀涓縐峃AT鍙仛NAPT錛屼粠鍚嶇О涓婃垜浠篃鍙互鐪嬪緱鍑猴紝NAPT涓嶄絾浼氭敼鍙樼粡榪囪繖涓狽AT璁懼鐨処P鏁版嵁鎶ョ殑IP鍦板潃錛岃繕浼氭敼鍙業P鏁版嵁鎶ョ殑TCP/UDP绔彛銆傚熀鏈琋AT鐨勮澶囧彲鑳芥垜浠鐨勪笉澶氾紙鍛靛懙錛屾垜娌℃湁瑙佸埌榪囷級錛孨APT鎵嶆槸鎴戜滑鐪熸璁ㄨ鐨勪富瑙掋傜湅涓嬪浘錛?br />聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 Server S1聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 18.181.0.31:1235聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 |
聽聽聽聽聽聽聽聽聽 ^聽 Session 1 (A-S1)聽 ^聽聽聽聽聽 |聽
聽聽聽聽聽聽聽聽聽 |聽 18.181.0.31:1235聽 |聽聽聽聽聽 |聽聽
聽聽聽聽聽聽聽聽聽 v 155.99.25.11:62000 v聽聽聽聽聽 |聽聽聽
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 |
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 NAT
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 155.99.25.11
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 |
聽聽聽聽聽聽聽聽聽 ^聽 Session 1 (A-S1)聽 ^聽聽聽聽聽 |聽
聽聽聽聽聽聽聽聽聽 |聽 18.181.0.31:1235聽 |聽聽聽聽聽 |聽
聽聽聽聽聽聽聽聽聽 v聽聽 10.0.0.1:1234聽聽聽 v聽聽聽聽聽 |聽
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 |
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 Client A
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 10.0.0.1:1234
聽聽聽 鏈変竴涓鏈夌綉緇?0.*.*.*錛孋lient A鏄叾涓殑涓鍙拌綆楁満錛岃繖涓綉緇滅殑緗戝叧錛堜竴涓狽AT璁懼錛夌殑澶栫綉IP鏄?55.99.25.11(搴旇榪樻湁涓涓唴緗戠殑IP鍦板潃錛屾瘮濡?0.0.0.10)銆傚鏋淐lient A涓殑鏌愪釜榪涚▼錛堣繖涓繘紼嬪垱寤轟簡涓涓猆DP Socket,榪欎釜Socket緇戝畾1234绔彛錛夋兂璁塊棶澶栫綉涓繪満18.181.0.31鐨?235绔彛錛岄偅涔堝綋鏁版嵁鍖呴氳繃NAT鏃朵細鍙戠敓浠涔堜簨鎯呭憿錛?br />聽聽聽 棣栧厛NAT浼氭敼鍙樿繖涓暟鎹寘鐨勫師IP鍦板潃錛屾敼涓?55.99.25.11銆傛帴鐫NAT浼氫負榪欎釜浼犺緭鍒涘緩涓涓猄ession錛圫ession鏄竴涓娊璞$殑姒傚康錛屽鏋滄槸TCP錛屼篃璁窼ession鏄敱涓涓猄YN鍖呭紑濮嬶紝浠ヤ竴涓狥IN鍖呯粨鏉熴傝孶DP鍛紝浠ヨ繖涓狪P鐨勮繖涓鍙g殑絎竴涓猆DP寮濮嬶紝緇撴潫鍛紝鍛靛懙錛屼篃璁告槸鍑犲垎閽燂紝涔熻鏄嚑灝忔椂錛岃繖瑕佺湅鍏蜂綋鐨勫疄鐜頒簡錛夊茍涓旂粰榪欎釜Session鍒嗛厤涓涓鍙o紝姣斿62000錛岀劧鍚庢敼鍙樿繖涓暟鎹寘鐨勬簮绔彛涓?2000銆傛墍浠ユ湰鏉ユ槸錛?0.0.0.1:1234->18.181.0.31:1235錛夌殑鏁版嵁鍖呭埌浜嗕簰鑱旂綉涓婂彉涓轟簡錛?55.99.25.11:62000->18.181.0.31:1235錛夈?br />聽聽聽 涓鏃AT鍒涘緩浜嗕竴涓猄ession鍚庯紝NAT浼氳浣?2000绔彛瀵瑰簲鐨勬槸10.0.0.1鐨?234绔彛錛屼互鍚庝粠18.181.0.31鍙戦佸埌62000绔彛鐨勬暟鎹細琚玁AT鑷姩鐨勮漿鍙戝埌10.0.0.1涓娿傦紙娉ㄦ剰錛氳繖閲屾槸璇?8.181.0.31鍙戦佸埌62000绔彛鐨勬暟鎹細琚漿鍙戯紝鍏朵粬鐨処P鍙戦佸埌榪欎釜绔彛鐨勬暟鎹皢琚玁AT鎶涘純錛夎繖鏍稢lient A灝變笌Server S1寤虹珛浠ヤ簡涓涓繛鎺ャ?/p>
聽聽聽 鍛靛懙錛屼笂闈㈢殑鍩虹鐭ヨ瘑鍙兘寰堝浜洪兘鐭ラ亾浜嗭紝閭d箞涓嬮潰鏄叧閿殑閮ㄥ垎浜嗐?br />聽聽聽 鐪嬬湅涓嬮潰鐨勬儏鍐碉細
聽聽聽 Server S1聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 Server S2
聽18.181.0.31:1235聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 138.76.29.7:1235
聽聽聽聽聽聽聽 |聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 |
聽聽聽聽聽聽聽 |聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 |
聽聽聽聽聽聽聽 +----------------------+----------------------+
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 |
聽聽 ^聽 Session 1 (A-S1)聽 ^聽聽聽聽聽 |聽聽聽聽聽 ^聽 Session 2 (A-S2)聽 ^
聽聽 |聽 18.181.0.31:1235聽 |聽聽聽聽聽 |聽聽聽聽聽 |聽 138.76.29.7:1235聽 |
聽聽 v 155.99.25.11:62000 v聽聽聽聽聽 |聽聽聽聽聽 v 155.99.25.11:62000 v
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 |
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 Cone NAT
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 155.99.25.11
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 |
聽聽 ^聽 Session 1 (A-S1)聽 ^聽聽聽聽聽 |聽聽聽聽聽 ^聽 Session 2 (A-S2)聽 ^
聽聽 |聽 18.181.0.31:1235聽 |聽聽聽聽聽 |聽聽聽聽聽 |聽 138.76.29.7:1235聽 |
聽聽 v聽聽 10.0.0.1:1234聽聽聽 v聽聽聽聽聽 |聽聽聽聽聽 v聽聽 10.0.0.1:1234聽聽聽 v
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 |
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 Client A
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 10.0.0.1:1234
聽聽聽 鎺ヤ笂闈㈢殑渚嬪瓙錛屽鏋淐lient A鐨勫師鏉ラ偅涓猄ocket(緇戝畾浜?234绔彛鐨勯偅涓猆DP Socket)鍙堟帴鐫鍚戝彟澶栦竴涓猄erver S2鍙戦佷簡涓涓猆DP鍖咃紝閭d箞榪欎釜UDP鍖呭湪閫氳繃NAT鏃朵細鎬庝箞鏍峰憿錛?br />聽聽聽 榪欐椂鍙兘浼氭湁涓ょ鎯呭喌鍙戠敓錛屼竴縐嶆槸NAT鍐嶆鍒涘緩涓涓猄ession錛屽茍涓斿啀嬈′負榪欎釜Session鍒嗛厤涓涓鍙e彿錛堟瘮濡傦細62001錛夈傚彟澶栦竴縐嶆槸NAT鍐嶆鍒涘緩涓涓猄ession錛屼絾鏄笉浼氭柊鍒嗛厤涓涓鍙e彿錛岃屾槸鐢ㄥ師鏉ュ垎閰嶇殑绔彛鍙?2000銆傚墠涓縐峃AT鍙仛Symmetric NAT錛屽悗涓縐嶅彨鍋欳one NAT銆傛垜浠湡鏈涙垜浠殑NAT鏄浜岀錛屽懙鍛碉紝濡傛灉浣犵殑NAT鍒氬ソ鏄涓縐嶏紝閭d箞寰堝彲鑳戒細鏈夊緢澶歅2P杞歡澶辯伒銆傦紙鍙互搴嗗垢鐨勬槸錛岀幇鍦ㄧ粷澶у鏁扮殑NAT灞炰簬鍚庤咃紝鍗矯one NAT錛?br />聽聽
聽聽聽 濂戒簡錛屾垜浠湅鍒幫紝閫氳繃NAT,瀛愮綉鍐呯殑璁$畻鏈哄悜澶栬繛緇撴槸寰堝鏄撶殑錛圢AT鐩稿綋浜庨忔槑鐨勶紝瀛愮綉鍐呯殑鍜屽緗戠殑璁$畻鏈轟笉鐢ㄧ煡閬揘AT鐨勬儏鍐碉級銆?br />聽聽聽 浣嗘槸濡傛灉澶栭儴鐨勮綆楁満鎯寵闂瓙緗戝唴鐨勮綆楁満灝辨瘮杈冨洶闅句簡錛堣岃繖姝f槸P2P鎵闇瑕佺殑錛夈?br />聽聽聽 閭d箞鎴戜滑濡傛灉鎯充粠澶栭儴鍙戦佷竴涓暟鎹姤緇欏唴緗戠殑璁$畻鏈烘湁浠涔堝姙娉曞憿錛熼鍏堬紝鎴戜滑蹇呴』鍦ㄥ唴緗戠殑NAT涓婃墦涓婁竴涓滄礊鈥濓紙涔熷氨鏄墠闈㈡垜浠鐨勫湪NAT涓婂緩绔嬩竴涓猄ession錛夛紝榪欎釜媧炰笉鑳界敱澶栭儴鏉ユ墦錛屽彧鑳界敱鍐呯綉鍐呯殑涓繪満鏉ユ墦銆傝屼笖榪欎釜媧炴槸鏈夋柟鍚戠殑錛屾瘮濡備粠鍐呴儴鏌愬彴涓繪満錛堟瘮濡傦細192.168.0.10錛夊悜澶栭儴鐨勬煇涓狪P(姣斿錛?19.237.60.1)鍙戦佷竴涓猆DP鍖咃紝閭d箞灝卞湪榪欎釜鍐呯綉鐨凬AT璁懼涓婃墦浜嗕竴涓柟鍚戜負219.237.60.1鐨勨滄礊鈥濓紝錛堣繖灝辨槸縐頒負UDP Hole Punching鐨勬妧鏈級浠ュ悗219.237.60.1灝卞彲浠ラ氳繃榪欎釜媧炰笌鍐呯綉鐨?92.168.0.10鑱旂郴浜嗐傦紙浣嗘槸鍏朵粬鐨処P涓嶈兘鍒╃敤榪欎釜媧烇級銆?/p>
鍛靛懙錛岀幇鍦ㄨ杞埌鎴戜滑鐨勬棰楶2P浜嗐傛湁浜嗕笂闈㈢殑鐞嗚錛屽疄鐜頒袱涓唴緗戠殑涓繪満閫氳灝卞樊鏈鍚庝竴姝ヤ簡錛氶偅灝辨槸楦$敓铔嬭繕鏄泲鐢熼浮鐨勯棶棰樹簡錛屼袱杈歸兘鏃犳硶涓誨姩鍙戝嚭榪炴帴璇鋒眰錛岃皝涔熶笉鐭ラ亾璋佺殑鍏綉鍦板潃錛岄偅鎴戜滑濡備綍鏉ユ墦榪欎釜媧炲憿錛熸垜浠渶瑕佷竴涓腑闂翠漢鏉ヨ仈緋昏繖涓や釜鍐呯綉涓繪満銆?br />聽聽聽 鐜板湪鎴戜滑鏉ョ湅鐪嬩竴涓狿2P杞歡鐨勬祦紼嬶紝浠ヤ笅鍥句負渚嬶細
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 Server S 錛?19.237.60.1錛?br />聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 |
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 |
聽聽 +----------------------+----------------------+
聽聽 |聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 |
聽NAT A (澶栫綉IP:202.187.45.3)聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 NAT B (澶栫綉IP:187.34.1.56)
聽聽 |聽聽 (鍐呯綉IP:192.168.0.1)聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 | (鍐呯綉IP:192.168.0.1)
聽聽 |聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 |
Client A聽 (192.168.0.20:4000)聽聽聽聽聽聽聽聽聽聽聽聽 Client B (192.168.0.10:40000)
聽聽聽 棣栧厛錛孋lient A鐧誨綍鏈嶅姟鍣紝NAT A涓鴻繖嬈$殑Session鍒嗛厤浜嗕竴涓鍙?0000錛岄偅涔圫erver S鏀跺埌鐨凜lient A鐨勫湴鍧鏄?02.187.45.3:60000錛岃繖灝辨槸Client A鐨勫緗戝湴鍧浜嗐傚悓鏍鳳紝Client B鐧誨綍Server S錛孨AT B緇欐嬈ession鍒嗛厤鐨勭鍙f槸40000錛岄偅涔圫erver S鏀跺埌鐨凚鐨勫湴鍧鏄?87.34.1.56:40000銆?br />聽聽聽 姝ゆ椂錛孋lient A涓嶤lient B閮藉彲浠ヤ笌Server S閫氫俊浜嗐傚鏋淐lient A姝ゆ椂鎯崇洿鎺ュ彂閫佷俊鎭粰Client B錛岄偅涔堜粬鍙互浠嶴erver S閭e効鑾峰緱B鐨勫叕緗戝湴鍧187.34.1.56:40000錛屾槸涓嶆槸Client A鍚戣繖涓湴鍧鍙戦佷俊鎭疌lient B灝辮兘鏀跺埌浜嗗憿錛熺瓟妗堟槸涓嶈錛屽洜涓哄鏋滆繖鏍峰彂閫佷俊鎭紝NAT B浼氬皢榪欎釜淇℃伅涓㈠純錛堝洜涓鴻繖鏍風殑淇℃伅鏄笉璇瘋嚜鏉ョ殑錛屼負浜嗗畨鍏紝澶у鏁癗AT閮戒細鎵ц涓㈠純鍔ㄤ綔錛夈傜幇鍦ㄦ垜浠渶瑕佺殑鏄湪NAT B涓婃墦涓涓柟鍚戜負202.187.45.3錛堝嵆Client A鐨勫緗戝湴鍧錛夌殑媧烇紝閭d箞Client A鍙戦佸埌187.34.1.56:40000鐨勪俊鎭?Client B灝辮兘鏀跺埌浜嗐傝繖涓墦媧炲懡浠ょ敱璋佹潵鍙戝憿錛屽懙鍛碉紝褰撶劧鏄疭erver S銆?br />聽聽聽 鎬葷粨涓涓嬭繖涓繃紼嬶細濡傛灉Client A鎯沖悜Client B鍙戦佷俊鎭紝閭d箞Client A鍙戦佸懡浠ょ粰Server S錛岃姹係erver S鍛戒護Client B鍚慍lient A鏂瑰悜鎵撴礊銆傚懙鍛碉紝鏄笉鏄緢緇曞彛錛屼笉榪囨病鍏崇郴錛屾兂涓鎯沖氨寰堟竻妤氫簡錛屼綍鍐佃繕鏈夋簮浠g爜鍛紙渚佸笀璇磋繃錛氬湪婧愪唬鐮侀潰鍓嶆病鏈夌瀵?8錛夛級錛岀劧鍚嶤lient A灝卞彲浠ラ氳繃Client B鐨勫緗戝湴鍧涓嶤lient B閫氫俊浜嗐?br />聽聽聽
聽聽聽 娉ㄦ剰錛氫互涓婅繃紼嬪彧閫傚悎浜嶤one NAT鐨勬儏鍐碉紝濡傛灉鏄疭ymmetric NAT錛岄偅涔堝綋Client B鍚慍lient A鎵撴礊鐨勭鍙e凡緇忛噸鏂板垎閰嶄簡錛孋lient B灝嗘棤娉曠煡閬撹繖涓鍙o紙濡傛灉Symmetric NAT鐨勭鍙f槸欏哄簭鍒嗛厤鐨勶紝閭d箞鎴戜滑鎴栬鍙互鐚滄祴榪欎釜绔彛鍙鳳紝鍙槸鐢變簬鍙兘瀵艱嚧澶辮觸鐨勫洜绱犲お澶氾紝鎴戜滑涓嶆帹鑽愯繖縐嶇寽嫻嬬鍙g殑鏂規硶錛夈?br />聽聽聽
聽聽聽 涓嬮潰鏄竴涓ā鎷烶2P鑱婂ぉ鐨勮繃紼嬬殑婧愪唬鐮侊紝榪囩▼寰堢畝鍗曪紝P2PServer榪愯鍦ㄤ竴涓嫢鏈夊叕緗慖P鐨勮綆楁満涓婏紝P2PClient榪愯鍦ㄤ袱涓笉鍚岀殑NAT鍚庯紙娉ㄦ剰錛屽鏋滀袱涓鎴風榪愯鍦ㄤ竴涓狽AT鍚庯紝鏈▼搴忓緢鍙兘涓嶈兘榪愯姝e父錛岃繖鍙栧喅浜庝綘鐨凬AT鏄惁鏀寔loopback translation錛岃瑙?a >http://midcom-p2p.sourceforge.net/draft-ford-midcom-p2p-01.txt錛屽綋鐒訛紝姝ら棶棰樺彲浠ラ氳繃鍙屾柟鍏堝皾璇曡繛鎺ュ鏂圭殑鍐呯綉IP鏉ヨВ鍐籌紝浣嗘槸榪欎釜浠g爜鍙槸涓轟簡楠岃瘉鍘熺悊錛屽茍娌℃湁澶勭悊榪欎簺闂錛夛紝鍚庣櫥褰曠殑璁$畻鏈哄彲浠ヨ幏寰楀厛鐧誨綍璁$畻鏈虹殑鐢ㄦ埛鍚嶏紝鍚庣櫥褰曠殑璁$畻鏈洪氳繃send username message鐨勬牸寮忔潵鍙戦佹秷鎭傚鏋滃彂閫佹垚鍔燂紝璇存槑浣犲凡鍙栧緱浜嗙洿鎺ヤ笌瀵規柟榪炴帴鐨勬垚鍔熴?br />聽聽聽 紼嬪簭鐜板湪鏀寔涓変釜鍛戒護錛歴end , getu , exit
聽聽聽
聽聽聽 send鏍煎紡錛歴end username message
聽聽聽 鍔熻兘錛氬彂閫佷俊鎭粰username
聽聽聽
聽聽聽 getu鏍煎紡錛歡etu
聽聽聽 鍔熻兘錛氳幏寰楀綋鍓嶆湇鍔″櫒鐢ㄦ埛鍒楄〃
聽聽聽
聽聽聽 exit鏍煎紡錛歟xit
聽聽聽 鍔熻兘錛氭敞閿涓庢湇鍔″櫒鐨勮繛鎺ワ紙鏈嶅姟鍣ㄤ笉浼氳嚜鍔ㄧ洃嫻嬪鎴鋒槸鍚﹀悐綰匡級
聽聽聽聽聽聽聽
聽聽聽 浠g爜寰堢煭錛岀浉淇″緢瀹規槗鎳傦紝濡傛灉鏈変粈涔堥棶棰橈紝鍙互緇欐垜鍙戦偖浠?a href="mailto:zhouhuis22@sina.com">zhouhuis22@sina.com聽 鎴栬呭湪CSDN涓婂彂閫佺煭娑堟伅銆傚悓鏃訛紝嬈㈣繋杞彂姝ゆ枃錛屼絾甯屾湜淇濈暀浣滆呯増鏉?-錛夈?br />聽聽聽
聽聽聽 鏈鍚庢劅璋SDN緗戝弸 PiggyXP 鍜?Seilfer鐨勬祴璇曞府鍔?/p>
P2PServer.c
/* P2P 紼嬪簭鏈嶅姟绔?br />聽*
聽* 鏂囦歡鍚嶏細P2PServer.c
聽*
聽* 鏃ユ湡錛?004-5-21
聽*
聽* 浣滆咃細shootingstars(zhouhuis22@sina.com)
聽*
聽*/
#pragma comment(lib, "ws2_32.lib")
#include "windows.h"
#include "..\proto.h"
#include "..\Exception.h"
UserList ClientList;
void InitWinSock()
{
聽WSADATA wsaData;
聽if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
聽{
聽聽printf("Windows sockets 2.2 startup");
聽聽throw Exception("");
聽}
聽else{
聽聽printf("Using %s (Status: %s)\n",
聽聽聽wsaData.szDescription, wsaData.szSystemStatus);
聽聽printf("with API versions %d.%d to %d.%d\n\n",
聽聽聽LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion),
聽聽聽LOBYTE(wsaData.wHighVersion), HIBYTE(wsaData.wHighVersion));
聽聽
聽}
}
SOCKET mksock(int type)
{
聽SOCKET sock = socket(AF_INET, type, 0);
聽if (sock < 0)
聽{
聽聽聽聽聽聽聽 printf("create socket error");
聽聽throw Exception("");
聽}
聽return sock;
}
stUserListNode GetUser(char *username)
{
聽for(UserList::iterator UserIterator=ClientList.begin();
聽聽聽聽聽聽UserIterator!=ClientList.end();
聽聽聽聽聽聽聽++UserIterator)
聽{
聽聽if( strcmp( ((*UserIterator)->userName), username) == 0 )
聽聽聽return *(*UserIterator);
聽}
聽throw Exception("not find this user");
}
int main(int argc, char* argv[])
{
聽try{
聽聽InitWinSock();
聽聽
聽聽SOCKET PrimaryUDP;
聽聽PrimaryUDP = mksock(SOCK_DGRAM);
聽聽sockaddr_in local;
聽聽local.sin_family=AF_INET;
聽聽local.sin_port= htons(SERVER_PORT);
聽聽local.sin_addr.s_addr = htonl(INADDR_ANY);
聽聽int nResult=bind(PrimaryUDP,(sockaddr*)&local,sizeof(sockaddr));
聽聽if(nResult==SOCKET_ERROR)
聽聽聽throw Exception("bind error");
聽聽sockaddr_in sender;
聽聽stMessage recvbuf;
聽聽memset(&recvbuf,0,sizeof(stMessage));
聽聽// 寮濮嬩富寰幆.
聽聽// 涓誨驚鐜礋璐d笅闈㈠嚑浠朵簨鎯?
聽聽// 涓:璇誨彇瀹㈡埛绔櫥闄嗗拰鐧誨嚭娑堟伅,璁板綍瀹㈡埛鍒楄〃
聽聽// 浜?杞彂瀹㈡埛p2p璇鋒眰
聽聽for(;;)
聽聽{
聽聽聽int dwSender = sizeof(sender);
聽聽聽int ret = recvfrom(PrimaryUDP, (char *)&recvbuf, sizeof(stMessage), 0, (sockaddr *)&sender, &dwSender);
聽聽聽if(ret <= 0)
聽聽聽{
聽聽聽聽printf("recv error");
聽聽聽聽continue;
聽聽聽}
聽聽聽else
聽聽聽{
聽聽聽聽int messageType = recvbuf.iMessageType;
聽聽聽聽switch(messageType){
聽聽聽聽case LOGIN:
聽聽聽聽聽{
聽聽聽聽聽聽//聽 灝嗚繖涓敤鎴風殑淇℃伅璁板綍鍒扮敤鎴峰垪琛ㄤ腑
聽聽聽聽聽聽printf("has a user login : %s\n", recvbuf.message.loginmember.userName);
聽聽聽聽聽聽stUserListNode *currentuser = new stUserListNode();
聽聽聽聽聽聽strcpy(currentuser->userName, recvbuf.message.loginmember.userName);
聽聽聽聽聽聽currentuser->ip = ntohl(sender.sin_addr.S_un.S_addr);
聽聽聽聽聽聽currentuser->port = ntohs(sender.sin_port);
聽聽聽聽聽聽
聽聽聽聽聽聽ClientList.push_back(currentuser);
聽聽聽聽聽聽// 鍙戦佸凡緇忕櫥闄嗙殑瀹㈡埛淇℃伅
聽聽聽聽聽聽int nodecount = (int)ClientList.size();
聽聽聽聽聽聽sendto(PrimaryUDP, (const char*)&nodecount, sizeof(int), 0, (const sockaddr*)&sender, sizeof(sender));
聽聽聽聽聽聽for(UserList::iterator UserIterator=ClientList.begin();
聽聽聽聽聽聽聽聽UserIterator!=ClientList.end();
聽聽聽聽聽聽聽聽++UserIterator)
聽聽聽聽聽聽{
聽聽聽聽聽聽聽sendto(PrimaryUDP, (const char*)(*UserIterator), sizeof(stUserListNode), 0, (const sockaddr*)&sender, sizeof(sender));
聽聽聽聽聽聽}
聽聽聽聽聽聽break;
聽聽聽聽聽}
聽聽聽聽case LOGOUT:
聽聽聽聽聽{
聽聽聽聽聽聽// 灝嗘瀹㈡埛淇℃伅鍒犻櫎
聽聽聽聽聽聽printf("has a user logout : %s\n", recvbuf.message.logoutmember.userName);
聽聽聽聽聽聽UserList::iterator removeiterator = NULL;
聽聽聽聽聽聽for(UserList::iterator UserIterator=ClientList.begin();
聽聽聽聽聽聽聽UserIterator!=ClientList.end();
聽聽聽聽聽聽聽++UserIterator)
聽聽聽聽聽聽{
聽聽聽聽聽聽聽if( strcmp( ((*UserIterator)->userName), recvbuf.message.logoutmember.userName) == 0 )
聽聽聽聽聽聽聽{
聽聽聽聽聽聽聽聽removeiterator = UserIterator;
聽聽聽聽聽聽聽聽break;
聽聽聽聽聽聽聽}
聽聽聽聽聽聽}
聽聽聽聽聽聽if(removeiterator != NULL)
聽聽聽聽聽聽聽ClientList.remove(*removeiterator);
聽聽聽聽聽聽break;
聽聽聽聽聽}
聽聽聽聽case P2PTRANS:
聽聽聽聽聽{
聽聽聽聽聽聽// 鏌愪釜瀹㈡埛甯屾湜鏈嶅姟绔悜鍙﹀涓涓鎴峰彂閫佷竴涓墦媧炴秷鎭?br />聽聽聽聽聽聽printf("%s wants to p2p %s\n",inet_ntoa(sender.sin_addr),recvbuf.message.translatemessage.userName);
聽聽聽聽聽聽stUserListNode node = GetUser(recvbuf.message.translatemessage.userName);
聽聽聽聽聽聽sockaddr_in remote;
聽聽聽聽聽聽remote.sin_family=AF_INET;
聽聽聽聽聽聽remote.sin_port= htons(node.port);
聽聽聽聽聽聽remote.sin_addr.s_addr = htonl(node.ip);
聽聽聽聽聽聽in_addr tmp;
聽聽聽聽聽聽tmp.S_un.S_addr = htonl(node.ip);
聽聽聽聽聽聽printf("the address is %s,and port is %d\n",inet_ntoa(tmp), node.port);
聽聽聽聽聽聽stP2PMessage transMessage;
聽聽聽聽聽聽transMessage.iMessageType = P2PSOMEONEWANTTOCALLYOU;
聽聽聽聽聽聽transMessage.iStringLen = ntohl(sender.sin_addr.S_un.S_addr);
聽聽聽聽聽聽transMessage.Port = ntohs(sender.sin_port);
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽
聽聽聽聽聽聽sendto(PrimaryUDP,(const char*)&transMessage, sizeof(transMessage), 0, (const sockaddr *)&remote, sizeof(remote));
聽聽聽聽聽聽break;
聽聽聽聽聽}
聽聽聽聽
聽聽聽聽case GETALLUSER:
聽聽聽聽聽{
聽聽聽聽聽聽int command = GETALLUSER;
聽聽聽聽聽聽sendto(PrimaryUDP, (const char*)&command, sizeof(int), 0, (const sockaddr*)&sender, sizeof(sender));
聽聽聽聽聽聽int nodecount = (int)ClientList.size();
聽聽聽聽聽聽sendto(PrimaryUDP, (const char*)&nodecount, sizeof(int), 0, (const sockaddr*)&sender, sizeof(sender));
聽聽聽聽聽聽for(UserList::iterator UserIterator=ClientList.begin();
聽聽聽聽聽聽聽聽UserIterator!=ClientList.end();
聽聽聽聽聽聽聽聽++UserIterator)
聽聽聽聽聽聽{
聽聽聽聽聽聽聽sendto(PrimaryUDP, (const char*)(*UserIterator), sizeof(stUserListNode), 0, (const sockaddr*)&sender, sizeof(sender));
聽聽聽聽聽聽}
聽聽聽聽聽聽break;
聽聽聽聽聽}
聽聽聽聽}
聽聽聽}
聽聽}
聽}
聽catch(Exception &e)
聽{
聽聽printf(e.GetMessage());
聽聽return 1;
聽}
聽return 0;
}
/* P2P 紼嬪簭瀹㈡埛绔?br />聽*
聽* 鏂囦歡鍚嶏細P2PClient.c
聽*
聽* 鏃ユ湡錛?004-5-21
聽*
聽* 浣滆咃細shootingstars(zhouhuis22@sina.com)
聽*
聽*/
#pragma comment(lib,"ws2_32.lib")
#include "windows.h"
#include "..\proto.h"
#include "..\Exception.h"
#include <iostream>
using namespace std;
UserList ClientList;
聽
#define COMMANDMAXC 256
#define MAXRETRY聽聽聽 5
SOCKET PrimaryUDP;
char UserName[10];
char ServerIP[20];
bool RecvedACK;
void InitWinSock()
{
聽WSADATA wsaData;
聽if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
聽{
聽聽printf("Windows sockets 2.2 startup");
聽聽throw Exception("");
聽}
聽else{
聽聽printf("Using %s (Status: %s)\n",
聽聽聽wsaData.szDescription, wsaData.szSystemStatus);
聽聽printf("with API versions %d.%d to %d.%d\n\n",
聽聽聽LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion),
聽聽聽LOBYTE(wsaData.wHighVersion), HIBYTE(wsaData.wHighVersion));
聽}
}
SOCKET mksock(int type)
{
聽SOCKET sock = socket(AF_INET, type, 0);
聽if (sock < 0)
聽{
聽聽聽聽聽聽聽 printf("create socket error");
聽聽throw Exception("");
聽}
聽return sock;
}
stUserListNode GetUser(char *username)
{
聽for(UserList::iterator UserIterator=ClientList.begin();
聽聽聽聽聽聽UserIterator!=ClientList.end();
聽聽聽聽聽聽聽++UserIterator)
聽{
聽聽if( strcmp( ((*UserIterator)->userName), username) == 0 )
聽聽聽return *(*UserIterator);
聽}
聽throw Exception("not find this user");
}
void BindSock(SOCKET sock)
{
聽sockaddr_in sin;
聽sin.sin_addr.S_un.S_addr = INADDR_ANY;
聽sin.sin_family = AF_INET;
聽sin.sin_port = 0;
聽
聽if (bind(sock, (struct sockaddr*)&sin, sizeof(sin)) < 0)
聽聽throw Exception("bind error");
}
void ConnectToServer(SOCKET sock,char *username, char *serverip)
{
聽sockaddr_in remote;
聽remote.sin_addr.S_un.S_addr = inet_addr(serverip);
聽remote.sin_family = AF_INET;
聽remote.sin_port = htons(SERVER_PORT);
聽
聽stMessage sendbuf;
聽sendbuf.iMessageType = LOGIN;
聽strncpy(sendbuf.message.loginmember.userName, username, 10);
聽sendto(sock, (const char*)&sendbuf, sizeof(sendbuf), 0, (const sockaddr*)&remote,sizeof(remote));
聽int usercount;
聽int fromlen = sizeof(remote);
聽int iread = recvfrom(sock, (char *)&usercount, sizeof(int), 0, (sockaddr *)&remote, &fromlen);
聽if(iread<=0)
聽{
聽聽throw Exception("Login error\n");
聽}
聽// 鐧誨綍鍒版湇鍔$鍚庯紝鎺ユ敹鏈嶅姟绔彂鏉ョ殑宸茬粡鐧誨綍鐨勭敤鎴風殑淇℃伅
聽cout<<"Have "<<usercount<<" users logined server:"<<endl;
聽for(int i = 0;i<usercount;i++)
聽{
聽聽stUserListNode *node = new stUserListNode;
聽聽recvfrom(sock, (char*)node, sizeof(stUserListNode), 0, (sockaddr *)&remote, &fromlen);
聽聽ClientList.push_back(node);
聽聽cout<<"Username:"<<node->userName<<endl;
聽聽in_addr tmp;
聽聽tmp.S_un.S_addr = htonl(node->ip);
聽聽cout<<"UserIP:"<<inet_ntoa(tmp)<<endl;
聽聽cout<<"UserPort:"<<node->port<<endl;
聽聽cout<<""<<endl;
聽}
}
void OutputUsage()
{
聽cout<<"You can input you command:\n"
聽聽<<"Command Type:\"send\",\"exit\",\"getu\"\n"
聽聽<<"Example : send Username Message\n"
聽聽<<"聽聽聽聽聽聽聽聽聽 exit\n"
聽聽<<"聽聽聽聽聽聽聽聽聽 getu\n"
聽聽<<endl;
}
/* 榪欐槸涓昏鐨勫嚱鏁幫細鍙戦佷竴涓秷鎭粰鏌愪釜鐢ㄦ埛(C)
聽*嫻佺▼錛氱洿鎺ュ悜鏌愪釜鐢ㄦ埛鐨勫緗慖P鍙戦佹秷鎭紝濡傛灉姝ゅ墠娌℃湁鑱旂郴榪?br />聽*聽聽聽聽聽 閭d箞姝ゆ秷鎭皢鏃犳硶鍙戦侊紝鍙戦佺絳夊緟瓚呮椂銆?br />聽*聽聽聽聽聽 瓚呮椂鍚庯紝鍙戦佺灝嗗彂閫佷竴涓姹備俊鎭埌鏈嶅姟绔紝
聽*聽聽聽聽聽 瑕佹眰鏈嶅姟绔彂閫佺粰瀹㈡埛C涓涓姹傦紝璇鋒眰C緇欐湰鏈哄彂閫佹墦媧炴秷鎭?br />聽*聽聽聽聽聽 浠ヤ笂嫻佺▼灝嗛噸澶峂AXRETRY嬈?br />聽*/
bool SendMessageTo(char *UserName, char *Message)
{
聽char realmessage[256];
聽unsigned int UserIP;
聽unsigned short UserPort;
聽bool FindUser = false;
聽for(UserList::iterator UserIterator=ClientList.begin();
聽聽聽聽聽聽UserIterator!=ClientList.end();
聽聽聽聽聽聽++UserIterator)
聽{
聽聽if( strcmp( ((*UserIterator)->userName), UserName) == 0 )
聽聽{
聽聽聽UserIP = (*UserIterator)->ip;
聽聽聽UserPort = (*UserIterator)->port;
聽聽聽FindUser = true;
聽聽}
聽}
聽if(!FindUser)
聽聽return false;
聽strcpy(realmessage, Message);
聽for(int i=0;i<MAXRETRY;i++)
聽{
聽聽RecvedACK = false;
聽聽sockaddr_in remote;
聽聽remote.sin_addr.S_un.S_addr = htonl(UserIP);
聽聽remote.sin_family = AF_INET;
聽聽remote.sin_port = htons(UserPort);
聽聽stP2PMessage MessageHead;
聽聽MessageHead.iMessageType = P2PMESSAGE;
聽聽MessageHead.iStringLen = (int)strlen(realmessage)+1;
聽聽int isend = sendto(PrimaryUDP, (const char *)&MessageHead, sizeof(MessageHead), 0, (const sockaddr*)&remote, sizeof(remote));
聽聽isend = sendto(PrimaryUDP, (const char *)&realmessage, MessageHead.iStringLen, 0, (const sockaddr*)&remote, sizeof(remote));
聽聽
聽聽// 絳夊緟鎺ユ敹綰跨▼灝嗘鏍囪淇敼
聽聽for(int j=0;j<10;j++)
聽聽{
聽聽聽if(RecvedACK)
聽聽聽聽return true;
聽聽聽else
聽聽聽聽Sleep(300);
聽聽}
聽聽// 娌℃湁鎺ユ敹鍒扮洰鏍囦富鏈虹殑鍥炲簲錛岃涓虹洰鏍囦富鏈虹殑绔彛鏄犲皠娌℃湁
聽聽// 鎵撳紑錛岄偅涔堝彂閫佽姹備俊鎭粰鏈嶅姟鍣紝瑕佹湇鍔″櫒鍛婅瘔鐩爣涓繪満
聽聽// 鎵撳紑鏄犲皠绔彛錛圲DP鎵撴礊錛?br />聽聽sockaddr_in server;
聽聽server.sin_addr.S_un.S_addr = inet_addr(ServerIP);
聽聽server.sin_family = AF_INET;
聽聽server.sin_port = htons(SERVER_PORT);
聽
聽聽stMessage transMessage;
聽聽transMessage.iMessageType = P2PTRANS;
聽聽strcpy(transMessage.message.translatemessage.userName, UserName);
聽聽sendto(PrimaryUDP, (const char*)&transMessage, sizeof(transMessage), 0, (const sockaddr*)&server, sizeof(server));
聽聽Sleep(100);// 絳夊緟瀵規柟鍏堝彂閫佷俊鎭?br />聽}
聽return false;
}
// 瑙f瀽鍛戒護錛屾殏鏃跺彧鏈塭xit鍜宻end鍛戒護
// 鏂板getu鍛戒護錛岃幏鍙栧綋鍓嶆湇鍔″櫒鐨勬墍鏈夌敤鎴?br />void ParseCommand(char * CommandLine)
{
聽if(strlen(CommandLine)<4)
聽聽return;
聽char Command[10];
聽strncpy(Command, CommandLine, 4);
聽Command[4]='\0';
聽if(strcmp(Command,"exit")==0)
聽{
聽聽stMessage sendbuf;
聽聽sendbuf.iMessageType = LOGOUT;
聽聽strncpy(sendbuf.message.logoutmember.userName, UserName, 10);
聽聽sockaddr_in server;
聽聽server.sin_addr.S_un.S_addr = inet_addr(ServerIP);
聽聽server.sin_family = AF_INET;
聽聽server.sin_port = htons(SERVER_PORT);
聽聽sendto(PrimaryUDP,(const char*)&sendbuf, sizeof(sendbuf), 0, (const sockaddr *)&server, sizeof(server));
聽聽shutdown(PrimaryUDP, 2);
聽聽closesocket(PrimaryUDP);
聽聽exit(0);
聽}
聽else if(strcmp(Command,"send")==0)
聽{
聽聽char sendname[20];
聽聽char message[COMMANDMAXC];
聽聽int i;
聽聽for(i=5;;i++)
聽聽{
聽聽聽if(CommandLine[i]!=' ')
聽聽聽聽sendname[i-5]=CommandLine[i];
聽聽聽else
聽聽聽{
聽聽聽聽sendname[i-5]='\0';
聽聽聽聽break;
聽聽聽}
聽聽}
聽聽strcpy(message, &(CommandLine[i+1]));
聽聽if(SendMessageTo(sendname, message))
聽聽聽printf("Send OK!\n");
聽聽else
聽聽聽printf("Send Failure!\n");
聽}
聽else if(strcmp(Command,"getu")==0)
聽{
聽聽int command = GETALLUSER;
聽聽sockaddr_in server;
聽聽server.sin_addr.S_un.S_addr = inet_addr(ServerIP);
聽聽server.sin_family = AF_INET;
聽聽server.sin_port = htons(SERVER_PORT);
聽聽sendto(PrimaryUDP,(const char*)&command, sizeof(command), 0, (const sockaddr *)&server, sizeof(server));
聽}
}
// 鎺ュ彈娑堟伅綰跨▼
DWORD WINAPI RecvThreadProc(LPVOID lpParameter)
{
聽sockaddr_in remote;
聽int sinlen = sizeof(remote);
聽stP2PMessage recvbuf;
聽for(;;)
聽{
聽聽int iread = recvfrom(PrimaryUDP, (char *)&recvbuf, sizeof(recvbuf), 0, (sockaddr *)&remote, &sinlen);
聽聽if(iread<=0)
聽聽{
聽聽聽printf("recv error\n");
聽聽聽continue;
聽聽}
聽聽switch(recvbuf.iMessageType)
聽聽{
聽聽case P2PMESSAGE:
聽聽聽{
聽聽聽聽// 鎺ユ敹鍒癙2P鐨勬秷鎭?br />聽聽聽聽char *comemessage= new char[recvbuf.iStringLen];
聽聽聽聽int iread1 = recvfrom(PrimaryUDP, comemessage, 256, 0, (sockaddr *)&remote, &sinlen);
聽聽聽聽comemessage[iread1-1] = '\0';
聽聽聽聽if(iread1<=0)
聽聽聽聽聽throw Exception("Recv Message Error\n");
聽聽聽聽else
聽聽聽聽{
聽聽聽聽聽printf("Recv a Message:%s\n",comemessage);
聽聽聽聽聽
聽聽聽聽聽stP2PMessage sendbuf;
聽聽聽聽聽sendbuf.iMessageType = P2PMESSAGEACK;
聽聽聽聽聽sendto(PrimaryUDP, (const char*)&sendbuf, sizeof(sendbuf), 0, (const sockaddr*)&remote, sizeof(remote));
聽聽聽聽}
聽聽聽聽delete []comemessage;
聽聽聽聽break;
聽聽聽}
聽聽case P2PSOMEONEWANTTOCALLYOU:
聽聽聽{
聽聽聽聽// 鎺ユ敹鍒版墦媧炲懡浠わ紝鍚戞寚瀹氱殑IP鍦板潃鎵撴礊
聽聽聽聽printf("Recv p2someonewanttocallyou data\n");
聽聽聽聽sockaddr_in remote;
聽聽聽聽remote.sin_addr.S_un.S_addr = htonl(recvbuf.iStringLen);
聽聽聽聽remote.sin_family = AF_INET;
聽聽聽聽remote.sin_port = htons(recvbuf.Port);
聽聽聽聽// UDP hole punching
聽聽聽聽stP2PMessage message;
聽聽聽聽message.iMessageType = P2PTRASH;
聽聽聽聽sendto(PrimaryUDP, (const char *)&message, sizeof(message), 0, (const sockaddr*)&remote, sizeof(remote));
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽
聽聽聽聽break;
聽聽聽}
聽聽case P2PMESSAGEACK:
聽聽聽{
聽聽聽聽// 鍙戦佹秷鎭殑搴旂瓟
聽聽聽聽RecvedACK = true;
聽聽聽聽break;
聽聽聽}
聽聽case P2PTRASH:
聽聽聽{
聽聽聽聽// 瀵規柟鍙戦佺殑鎵撴礊娑堟伅錛屽拷鐣ユ帀銆?br />聽聽聽聽//do nothing ...
聽聽聽聽printf("Recv p2ptrash data\n");
聽聽聽聽break;
聽聽聽}
聽聽case GETALLUSER:
聽聽聽{
聽聽聽聽int usercount;
聽聽聽聽int fromlen = sizeof(remote);
聽聽聽聽int iread = recvfrom(PrimaryUDP, (char *)&usercount, sizeof(int), 0, (sockaddr *)&remote, &fromlen);
聽聽聽聽if(iread<=0)
聽聽聽聽{
聽聽聽聽聽throw Exception("Login error\n");
聽聽聽聽}
聽聽聽聽
聽聽聽聽ClientList.clear();
聽聽聽聽cout<<"Have "<<usercount<<" users logined server:"<<endl;
聽聽聽聽for(int i = 0;i<usercount;i++)
聽聽聽聽{
聽聽聽聽聽stUserListNode *node = new stUserListNode;
聽聽聽聽聽recvfrom(PrimaryUDP, (char*)node, sizeof(stUserListNode), 0, (sockaddr *)&remote, &fromlen);
聽聽聽聽聽ClientList.push_back(node);
聽聽聽聽聽cout<<"Username:"<<node->userName<<endl;
聽聽聽聽聽in_addr tmp;
聽聽聽聽聽tmp.S_un.S_addr = htonl(node->ip);
聽聽聽聽聽cout<<"UserIP:"<<inet_ntoa(tmp)<<endl;
聽聽聽聽聽cout<<"UserPort:"<<node->port<<endl;
聽聽聽聽聽cout<<""<<endl;
聽聽聽聽}
聽聽聽聽break;
聽聽聽}
聽聽}
聽}
}
int main(int argc, char* argv[])
{
聽try
聽{
聽聽InitWinSock();
聽聽
聽聽PrimaryUDP = mksock(SOCK_DGRAM);
聽聽BindSock(PrimaryUDP);
聽聽cout<<"Please input server ip:";
聽聽cin>>ServerIP;
聽聽cout<<"Please input your name:";
聽聽cin>>UserName;
聽聽ConnectToServer(PrimaryUDP, UserName, ServerIP);
聽聽HANDLE threadhandle = CreateThread(NULL, 0, RecvThreadProc, NULL, NULL, NULL);
聽聽CloseHandle(threadhandle);
聽聽OutputUsage();
聽聽for(;;)
聽聽{
聽聽聽char Command[COMMANDMAXC];
聽聽聽gets(Command);
聽聽聽ParseCommand(Command);
聽聽}
聽}
聽catch(Exception &e)
聽{
聽聽printf(e.GetMessage());
聽聽return 1;
聽}
聽return 0;
}
/* 寮傚父綾?br />聽*
聽* 鏂囦歡鍚嶏細Exception.h
聽*
聽* 鏃ユ湡錛?004.5.5
聽*
聽* 浣滆咃細shootingstars(zhouhuis22@sina.com)
聽*/
#ifndef __HZH_Exception__
#define __HZH_Exception__
#define EXCEPTION_MESSAGE_MAXLEN 256
#include "string.h"
class Exception
{
private:
聽char m_ExceptionMessage[EXCEPTION_MESSAGE_MAXLEN];
public:
聽Exception(char *msg)
聽{
聽聽strncpy(m_ExceptionMessage, msg, EXCEPTION_MESSAGE_MAXLEN);
聽}
聽char *GetMessage()
聽{
聽聽return m_ExceptionMessage;
聽}
};
#endif
/* P2P 紼嬪簭浼犺緭鍗忚
聽*
聽* 鏃ユ湡錛?004-5-21
聽*
聽* 浣滆咃細shootingstars(zhouhuis22@sina.com)
聽*
聽*/
#pragma once
#include <list>
// 瀹氫箟iMessageType鐨勫?br />#define LOGIN 1
#define LOGOUT 2
#define P2PTRANS 3
#define GETALLUSER聽 4
// 鏈嶅姟鍣ㄧ鍙?br />#define SERVER_PORT 2280
// Client鐧誨綍鏃跺悜鏈嶅姟鍣ㄥ彂閫佺殑娑堟伅
struct stLoginMessage
{
聽char userName[10];
聽char password[10];
};
// Client娉ㄩ攢鏃跺彂閫佺殑娑堟伅
struct stLogoutMessage
{
聽char userName[10];
};
// Client鍚戞湇鍔″櫒璇鋒眰鍙﹀涓涓狢lient(userName)鍚戣嚜宸辨柟鍚戝彂閫乁DP鎵撴礊娑堟伅
struct stP2PTranslate
{
聽char userName[10];
};
// Client鍚戞湇鍔″櫒鍙戦佺殑娑堟伅鏍煎紡
struct stMessage
{
聽int iMessageType;
聽union _message
聽{
聽聽stLoginMessage loginmember;
聽聽stLogoutMessage logoutmember;
聽聽stP2PTranslate translatemessage;
聽}message;
};
// 瀹㈡埛鑺傜偣淇℃伅
struct stUserListNode
{
聽char userName[10];
聽unsigned int ip;
聽unsigned short port;
};
// Server鍚慍lient鍙戦佺殑娑堟伅
struct stServerToClient
{
聽int iMessageType;
聽union _message
聽{
聽聽stUserListNode user;
聽}message;
};
//======================================
// 涓嬮潰鐨勫崗璁敤浜庡鎴風涔嬮棿鐨勯氫俊
//======================================
#define P2PMESSAGE 100聽聽聽聽聽聽聽聽聽聽聽聽聽聽 // 鍙戦佹秷鎭?br />#define P2PMESSAGEACK 101聽聽聽聽聽聽聽聽聽聽聽 // 鏀跺埌娑堟伅鐨勫簲絳?br />#define P2PSOMEONEWANTTOCALLYOU 102聽 // 鏈嶅姟鍣ㄥ悜瀹㈡埛绔彂閫佺殑娑堟伅
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 // 甯屾湜姝ゅ鎴風鍙戦佷竴涓猆DP鎵撴礊鍖?br />#define P2PTRASH聽聽聽聽聽聽聽 103聽聽聽聽聽聽聽聽聽 // 瀹㈡埛绔彂閫佺殑鎵撴礊鍖咃紝鎺ユ敹绔簲璇ュ拷鐣ユ娑堟伅
// 瀹㈡埛绔箣闂村彂閫佹秷鎭牸寮?br />struct stP2PMessage
{
聽int iMessageType;
聽int iStringLen;聽聽聽聽聽聽聽聽 // or IP address
聽unsigned short Port;
};
using namespace std;
typedef list<stUserListNode *> UserList;