udp伺服器如何只發不收
1. C#/VB.NET中 UDP協議連接伺服器問題...運行沒出錯..但是收不到信息.
伺服器先進行
Bind ()綁定伺服器的埠
然後BeginReceive接受客戶端發送的數據
客戶端Bind ()綁定客戶端接受和發送數據的埠
SendTo()來發送數據就可以
不需要進行BeginConnect,因為UDP不需要連接
2. 請教一個JAVA UDP程序問題。我編了一個UDP通信程序,實現客戶端向伺服器端發送信息。
正如你所說,UDP不需要實時連接,客戶端只負責發送,不保證成功,服務端也只接收正確到達的數據包,你沒有起服務端之前的客戶端所發送的UDP數據包都屬於丟包,就像我們玩一些網游,如果網路不好,會出現一卡一卡的,本來在這下一秒突然移動到另一個地方,中間移動的過程沒有出現,這就屬於丟包了。
3. 採用UDP的echo伺服器示例
UDP是面向無連接的,使用起來比較簡單,打開socke之後,指定目標埠,直接進行接收和發送:
socket本身提供了一些介面:
需要注意的是, boost.asio.buffer 是一種介面適配器,通過介面進行發送和接收,必須有對應的數據緩沖區提供數據或者存儲空間。
同步接收同步發送的UDP伺服器也比較簡單,創建一個綁定到本地埠的socket,然後就是接收及發送動作:
同步操作是不需要運行IO服務的,以最常規的方式來進行發送和接收,注意接收時如果接收到全部消息,即EOF也是通過報錯形式,錯誤碼為 error::message_size 。
實現非同步的UDP伺服器就略顯復雜,需要保證IO服務運行,發起非同步操作時要注意數據緩沖區生命周期:
可以看到 do_recv 方法發起了一個非同步接收操作,在操作完成回調中再次發起,構造伺服器時率先調用了 do_recv ,從而保證IO服務一直運行。
do_recv 方法在發起非同步操作前申請了一塊內存,接收的內容被保存在這塊內存之中,當 do_send 發起非同步發送操作時被借用,直到發送完成才將這段內存釋放掉。
在構造函數中啟動了一個線程來執行IO服務,並detach掉線程,從而保證伺服器不阻塞,在析構函數停止了IO服務。
需要注意到的是 remote_ep_ 在執行 do_send 時被 move 了,由於 remote_ep_ 標識了遠程埠,而且被聲明為成員變數,在接受操作中會被填充遠程埠內容,如果多個遠程主機同時發起,單個 remote_ep_ 是無法正常處理的,所以一旦內容被填充後,就會轉移出去給發送操作使用[個人理解,沒有實際測試和驗證]。
4. udp通訊過程客戶端可不可以不bind如果不bind則服務端如何向其發送信息
關鍵是recvfrom返回的客戶端addrClient是不能作為伺服器返回客戶端的地址使用的,即在sendto中不能使用由recvfrom返回得到的客戶端地址。 樓主將UDP通訊和TCP通訊搞混了,不過說實話這個是很正常的。當初我學的時候沒一本書是把網路通信編程寫清楚地,只能靠自己摸索。 socket可以理解為通信地址,它由協議,IP和埠組成。在UDP模式中,綁定的目的是要告訴操作系統,當網卡從外部接收到數據包時,操作系統就知道應該把這個數據包交給哪個應用程序。 具體是這樣的,網卡總是知道自己的IP是什麼,因此網卡接收到網線中的數據包時,會提取數據包的包頭,裡面含有的IP如果是網卡自己的IP,它就會把該數據包交給操作系統,如果不是就將該數據包丟棄,可以認為操作系統不知道有該數據包。操作系統接收到數據包後,會根據每個數據包包含的埠號,將該數據包發給不同的應用程序。操作系統怎麼會知道哪個埠號對應哪個應用程序呢?這個就是要求應用程序使用bind函數,將自己的埠號告訴操作系統。因此,所謂的埠沖突就是指其他應用程序已經通過bind告訴了操作系統該埠被它使用了,因此另外的應用程序就不能使用該埠了,即bind肯定失敗! 所以,bind肯定是由接受數據包的應用程序使用的,這樣的應用程序就是伺服器應用程序,也可以看到我們需要為bind提供IP和埠號。並且,當初我還在疑惑為什麼會有一個INADDR_ANY的IP指定,似乎bind根本不需要IP啊,只要埠就可以了。仔細一想才明白,因為一台主機可能會有2個網卡。因此,主機可能會有兩個IP,這樣bind這個函數允許我們自由指定需要綁定到哪塊網卡上的特定埠。也可以不指定,通過INADDR_ANY由操作系統為我們指定。譬如,13埠在第一塊網卡中被佔用了,我們就可以使用bind明確指定自己的應用程序接收來自第二塊網卡13埠的數據包。 UDP編程中作為客戶端發送數據時,是不需要指定自己的IP和埠的,因此無需使用bind綁定,直接在sendto指定伺服器的IP和埠就可以了。但實際上發送數據時,操作系統還是需要使用客戶端機器上的一個IP和埠號的,這個IP和埠號由操作系統指派,譬如在操作系統處理sendto時,它可以指派1005埠給UDP客戶端,此時如果有另一個客戶程序再使用bind注冊該埠,就會失敗了。但實際情況大家都知道,UDP數據包的發送是相當快的,這種沖突幾乎不存在,因為數據包發送後,即數據包通過網卡發到了網線中,操作系統就認為發送成功了,該埠就會被操作系統收回,標記「未使用」。 總結一下,UDP伺服器需要佔用一個IP和一個埠號,且是固定的,是在調用了bind函數成功後便確定下來了。UDP客戶端也需要使用一個IP和一個埠號,它們都是隨機的,這次發送可能是第一塊網卡,第二次可能是第二塊網卡,埠也如此。發送後,該埠就被操作系統收回,因此客戶端無法使用該埠接收來自伺服器的數據包。 因此不能使用recvfrom的客戶端的埠信息再調用sendto發送給客戶端,因為客戶端的電腦操作系統根本不會講該數據包交給客戶端應用程序。 以上用比較容易理解的概念介紹了下,其實精確說的話,很多事情不是操作系統做的,而是各種驅動程序完成的。具體怎麼修改代碼,樓主應該明白了吧,光改伺服器端的代碼,沒用,客戶端的代碼也要改。這也是為什麼UDP是不存在伺服器,客戶端之說的原因,因為任何一方給另一方發數據包,前提必須使另一方已經通過bind綁定了一個固定埠了。
5. 客戶端使用UDP協議不停的向伺服器發送數據,Java這邊需要存儲這些數據並進行處理,如何監控這個數據
2個方法,設置2個變數分別記載當前處理的queue下標A,(假設你的queue是結構體數組長度200),還有個表量記載還沒有操作的總數B。
1.保證每個數據都接收。即時沒有處理完也接收,循環加,從0-199再循環,另一個線程處理,從當前標記A開始往下處理,沒處理完一個A+1 B-1,接收線程沒接收一個B+1,B一直循環,QUEUE[B]接收數據,一定要注意,這2個變數和你的數組要加鎖,防止2個線程同時被修改
2.保證處理,如果沒處理完就不接收,加到B到上限就停止,但數據也是循環的存儲,其他方法和上面一樣,就是要注意加鎖
以上說的方法是數據先進先出,如果想做先進後出的話,就每次處理當前A的數據,然後向前回溯就可以了
6. 如何修正安卓虛擬機收不到udp包的問題
前言
當我們做安卓開發時,大多數人還是習慣用虛擬機,畢竟真機巴拉來巴拉去的不如滑鼠方便,尤其是調試一些功能模塊時,比如socket udp , 下文說明如何用as+虛擬機調試 socket udp, 實測
如何搭建udp伺服器和客戶端不提了,簡單的搭建隨便找一個吧
首先我們的前提是 我們在pc上建立了一個UDP伺服器,目的是通過這伺服器給虛擬機發送一個udp包
但如何發送這個包呢?
如果想當然的這樣做在server上給"127.0.0.1:9014"發送包,然後在虛擬機的9014埠接受包,你會發現無論發多少次,虛擬機什麼都收不到。 原因是,你這個包並不是發給虛擬機了,而是發給了本地埠,
也許你會說,給虛擬機發應該用虛擬機的ip地址,好的,通過嘗試我們發現給虛擬機的ip地址+9014埠,仍然無法收到。(我用工具查看的虛擬機ip地址是10.0.2.15)
正確步驟
1.把PC埠9014映射到虛擬機,意思就是當PC 9014埠收到udp包,它會轉發給虛擬機相應的埠
使用windows程序telnet即可達到映射的目的,(注意Telnet在win10需要開啟,可查找怎麼開啟這個程序)
打開cmd 輸入如下命令連接到本地虛擬機
telnet localhost 5554
連接成功後他會提示你輸入驗證,並告訴你驗證碼在哪裡
7. UDP 並發伺服器,大家幫忙看一看!該如何解決
UDP2000個客戶端左右 並發
單個數據包最大512位元組
Internet 10MB帶寬
要求效率(盡可能快,盡可能少丟包),這種情況下用哪種通訊模型比較有優勢!
想用IOCP,因為和select模型相比,這個稍微熟悉一點,也在項目中用過,不過是TCP的。
有兩個問題,大家懂得的幫忙給指導一下:
是否可以理解為UDP模式下,一次recvfrom 只對應一次sendto。
2.能否對服務端的套接字同時投遞多個WsaRecvFrom,能否在多個線程中同時投遞WsaSendTo和WsaRecvFrom。
------解決方案--------------------------------------------------------
-------------------------------------
等不到,包被截斷了。
2.能否對服務端的套接字同時投遞多個WsaRecvFrom,能否在多個線程中同時投遞WsaSendTo和WsaRecvFrom。
--------------------------
其實,我個人認為對udp而言,不用iocp也可以滿足。 首先sendto都是立即完成的,無需非同步操作。而recvfrom可以只需阻塞一個線程就夠了,不需要重疊操作。
------解決方案--------------------------------------------------------
用UDX協議最可靠,效率高,開發簡單,非開源。
UDT開源,對於你這種2000客戶,夠用,開源。
------解決方案--------------------------------------------------------
1.sendto 10k,接受部分要麼收到10k,要麼全部丟失,不會出現部分收到的情況。
------解決方案--------------------------------------------------------
-------------------------------------
在區域網可以,公網,一般1K也收不到。
2.能否對服務端的套接字同時投遞多個WsaRecvFrom,能否在多個線程中同時投遞WsaSendTo和WsaRecvFrom。
--------------------------完全可以
------解決方案--------------------------------------------------------
1.如果UDP數據在傳輸過程中被分包,則你需要對數據包進行標識,已確保獲取的包完整。一次recvfrom並不對應一次sendto,考慮UDP不可靠傳輸的因素。
2.不可以,因為sendto和recvfrom都是對同一個資源Socket進行操作。如果在多個線程中對同一個資源進行操作,如果不加鎖的情況下,會非常可怕的。而且,如果你加鎖了,其實還不如單線程操作。
按照你的需求最好還是採用UDP,不過可以考慮組播。
2.API調用完全沒有問題。但是接到的數據可能和發送的數據次序不一樣,這本身是UDP亂序特性決定了的。而且你發送方可能是多線程,從API層面來說,這些調用都是可以的,完全沒有問題。但是給你接收方處理帶來一系列問題。
8. UDP類型的伺服器和客戶端,只能是客戶端最先發送數據
UDP沒有 客戶端 和伺服器的區分,隨便那個先發都可以。
不同的機器發過來也行。只要發到相應的ip 和埠就行了。
因為UDP和TCP不同,UDP是不需要首先建立連接的。