锘??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲国产精品无码成人片久久,久久综合久久综合久久,久久人人青草97香蕉http://www.shnenglu.com/shootingstars/category/4489.htmlzh-cnThu, 22 May 2008 20:24:16 GMTThu, 22 May 2008 20:24:16 GMT60P2P涔婾DP絀塊廚AT鐨勫師鐞嗕笌瀹炵幇錛堥檮婧愪唬鐮侊級http://www.shnenglu.com/shootingstars/archive/2007/06/12/26140.htmlshootingstarsshootingstarsTue, 12 Jun 2007 05:23:00 GMThttp://www.shnenglu.com/shootingstars/archive/2007/06/12/26140.htmlhttp://www.shnenglu.com/shootingstars/comments/26140.htmlhttp://www.shnenglu.com/shootingstars/archive/2007/06/12/26140.html#Feedback0http://www.shnenglu.com/shootingstars/comments/commentRss/26140.htmlhttp://www.shnenglu.com/shootingstars/services/trackbacks/26140.html浣滆咃細shootingstars | 鏃ユ湡錛?004-05-25 | 瀛椾綋錛氬ぇ 涓?灝?br>
P2P 涔?UDP絀塊廚AT鐨勫師鐞嗕笌瀹炵幇錛堥檮婧愪唬鐮侊級
鍘熷垱錛歴hootingstars
鍙傝冿細http://midcom-p2p.sourceforge.net/draft-ford-midcom-p2p-01.txt

璁哄潧涓婄粡甯告湁瀵筆2P鍘熺悊鐨勮璁猴紝浣嗘槸璁ㄨ褰掕璁猴紝寰堝皯鏈夊疄璐ㄧ殑涓滆タ浜х敓錛堟簮浠g爜錛夈傚懙鍛碉紝鍦ㄨ繖閲屾垜灝辯敤鑷繁瀹炵幇鐨勪竴涓簮浠g爜鏉ヨ鏄嶶DP絀胯秺NAT鐨勫師鐞嗐?br>
棣栧厛鍏堜粙緇嶄竴浜涘熀鏈蹇碉細
    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叏鐞冨敮涓鐨?IP鍦板潃銆傚鏋滆繖浜涜妭鐐歸渶瑕佽闂閮ㄧ綉緇滐紝閭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鍦板潃錛屾瘮濡?10.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绔彛鐨勬暟鎹細琚漿鍙戯紝鍏朵粬鐨?IP鍙戦佸埌榪欎釜绔彛鐨勬暟鎹皢琚玁AT鎶涘純錛夎繖鏍稢lient A灝變笌Server S1寤虹珛浠ヤ簡涓涓繛鎺ャ?br>
    鍛靛懙錛屼笂闈㈢殑鍩虹鐭ヨ瘑鍙兘寰堝浜洪兘鐭ラ亾浜嗭紝閭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涓婃墦涓婁竴涓?#8220;媧?#8221;錛堜篃灝辨槸鍓嶉潰鎴戜滑璇寸殑鍦∟AT涓婂緩绔嬩竴涓?Session錛夛紝榪欎釜媧炰笉鑳界敱澶栭儴鏉ユ墦錛屽彧鑳界敱鍐呯綉鍐呯殑涓繪満鏉ユ墦銆傝屼笖榪欎釜媧炴槸鏈夋柟鍚戠殑錛屾瘮濡備粠鍐呴儴鏌愬彴涓繪満錛堟瘮濡傦細192.168.0.10錛夊悜澶栭儴鐨勬煇涓狪P(姣斿錛?19.237.60.1)鍙戦佷竴涓猆DP鍖咃紝閭d箞灝卞湪榪欎釜鍐呯綉鐨凬AT璁懼涓婃墦浜嗕竴涓柟鍚戜負219.237.60.1鐨?#8220;媧?#8221;錛岋紙榪欏氨鏄О涓篣DP Hole Punching鐨勬妧鏈級浠ュ悗219.237.60.1灝卞彲浠ラ氳繃榪欎釜媧炰笌鍐呯綉鐨?92.168.0.10鑱旂郴浜嗐傦紙浣嗘槸鍏朵粬鐨処P涓嶈兘鍒╃敤榪欎釜媧烇級銆?br>
鍛靛懙錛岀幇鍦ㄨ杞埌鎴戜滑鐨勬棰楶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錛岃瑙乭ttp://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爜寰堢煭錛岀浉淇″緢瀹規槗鎳傦紝濡傛灉鏈変粈涔堥棶棰橈紝鍙互緇欐垜鍙戦偖浠秡houhuis22@sina.com  鎴栬呭湪CSDN涓婂彂閫佺煭娑堟伅銆傚悓鏃訛紝嬈㈣繋杞彂姝ゆ枃錛屼絾甯屾湜淇濈暀浣滆呯増鏉?-錛夈?br>   
    鏈鍚庢劅璋SDN緗戝弸 PiggyXP 鍜?Seilfer鐨勬祴璇曞府鍔?br>
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;

宸ョ▼涓嬭澆鍦板潃:http://www.ppcn.net/upload/2004_05/04052509317298.rar

]]>
欧美伊人久久大香线蕉综合 | 国产精品国色综合久久| 蜜桃麻豆WWW久久囤产精品| 久久精品亚洲AV久久久无码| 久久夜色精品国产噜噜麻豆| 国产精品美女久久久久网| 久久精品国产亚洲Aⅴ香蕉| 国产一区二区久久久| 久久精品国产亚洲沈樵| 伊人久久大香线蕉AV一区二区| 久久久国产乱子伦精品作者| 久久久久18| 韩国三级大全久久网站| 精品久久久一二三区| 精品久久综合1区2区3区激情 | 久久久久久久综合日本| 精品久久久久久中文字幕人妻最新| 狠狠色综合网站久久久久久久| 久久久噜噜噜久久熟女AA片| 久久久久一级精品亚洲国产成人综合AV区| 久久人人爽人人爽人人片AV高清| 精品久久久久中文字幕一区| 99久久99久久久精品齐齐| 久久久亚洲欧洲日产国码是AV| 久久免费观看视频| 99久久无码一区人妻| 久久精品国产一区| 国产成人久久精品激情| 人人狠狠综合久久88成人| 久久99国产精品久久99小说 | 久久午夜伦鲁片免费无码| 久久噜噜久久久精品66| 亚洲综合精品香蕉久久网97 | 亚洲欧美国产日韩综合久久 | 久久精品免费观看| 国产精品久久国产精品99盘 | AV无码久久久久不卡蜜桃| 久久99国内精品自在现线| 潮喷大喷水系列无码久久精品| 久久99精品国产麻豆| 精品久久久久久中文字幕|