SendTo
sendto() 用來將數據由指定的socket傳給對方主機。
參數s爲已建好連線的socket,如果利用UDP協議則不需經過連線操作。
參數msg指向欲連線的數據內容,參數flags 一般設0,詳細描述請參考send()。
參數to用來指定欲傳送的網絡地址,結構sockaddr請參考bind()。
參數tolen爲sockaddr的結構長度。
返回值 成功則返回實際傳送出去的字符數,失敗返回-1,錯誤原因存於errno 中。
錯誤代碼 EBADF 參數s非法的socket處理代碼。
EFAULT 參數中有一指針指向無法存取的內存空間。
ENOTSOCK 參數 s爲一文件描述詞,非socket。
EINTR 被信號所中斷。
sendmsg
send,sendto以及sendmsg系統調用用於發送消息到另一個套接字。
send函數在套接字處於連接狀態時方可使用。
而sendto和sendmsg在任何時候都可使用 。
sendmsg介紹 send,sendto,sendmsg方法用於從套接字發送消息。
send,sendto以及sendmsg系統調用用於發送消息到另一個套接字。
send函數在套接字處於連接狀態時方可使用。
而sendto和sendmsg在任何時候都可使用。
演示用法 下面的代碼片段演示了send,sendto,sendmsg函數的用法:
UDP客戶端使用connect()綁定一個地址和端口後,服務端收到此客戶端的數據時發現端口號錯誤?
我自己來回答一下吧! 我知道connect和bind的區別了。
哎,昨晚頭腦發熱,沒能理解書上兩段話的意思。
最近在看《TCP/IP網絡編程》一書,在講到UDP編程時,書上先是說: UDP中,調用sendto函數前應完成對套接字地址的分配工作,因此調用bind函數......另外,如果調用sendto函數時發現尚未分配地址信息,則在首次調用sendto時會給相應套接字自動分配IP和端口,而且此時分配的地址一直保留到程序結束爲止,因此也可用來與其他UDP套接字進行數據交換。
當然,IP用本主機IP,端口號隨意選擇一個尚未使用的端口號。
然後書上後面又有一個地方說: 通過sendto函數傳輸數據的過程大致分爲三個階段:- 第一階段:向UDP套接字註冊目標IP和端口號; - 第二階段:傳輸數據; - 第三階段:刪除UDP套接字中註冊的目標地址和端口號。
並且上述三個過程在每次調用sendto函數時都會發生,這樣就很浪費時間。
因此可以通過創建已連接UDP套接字來實現註冊地址信息,也就是通過connect來註冊地址信息。
由於是剛學網絡編程,因此看過之後,很懵圈,一個地方說在第一次調用sendto時就會註冊,一個地方說每次調用sendto時都會重新註冊。
睡完一覺,終於領悟了,書上說的原來是兩種地址,一個是本機地址,一個是目標地址。
書上說在第一次調用sendto函數前會註冊一個地址,這個是指的本機IP和端口。
給一個socket註冊本機IP和端口使用的是bind函數,而不是connect函數。
書上說每次調用sendto時都會重新註冊地址,這裏說的地址是指目標IP和端口。
同樣,給一個socket註冊目標IP和端口用的是connect函數。
因此,一個socket是同時包含兩個地址的,一個是目標地址,一個是本機地址。
註冊目標地址使用connect,註冊本機地址使用bind。
如果不註冊目標地址,則在每次調用sendto函數時都會自動註冊進去然後再自動解除。
如果不是先註冊本機地址,則在第一次調用sendto時就會自動註冊一個本機地址,且一直存在,不會主動解除。
其實不管在TCP中還是UDP中,connect不僅可以註冊目標地址,在第一次調用connect的時候,還會註冊本機地址(選一個可用的本機IP以及一個可用的端口自動註冊,無需程序員指定)。
一個socket的目標地址可以重複註冊多次,但是本機地址只能註冊一次,要麼顯式地使用bind註冊一次,要麼在第一次調用sendto函數(UDP)或者第一次調用connect()函數(TCP或UDP)時隱式地註冊進去。
還有,在UDP中通過sendto發送數據時,因爲始終要傳入目標服務器的地址,所以此時傳入sendto的socket所綁定的目標地址出錯,也不會有問題,目標服務器仍然能夠接受到數據,只不過此時如果目標服務器發送一個應答數據,則由於客戶端會使用recvfrom來接收數據,並且雖然也傳入了一個sockaddr參數,但是這個參數是用於接收的,recvfrom函數所接收的目標是sock中所綁定的目標地址。
因爲你設置的不正確,所以recvfrom是接收不到目標服務器返回來的數據的。
對於recvfrom函數,如果傳入的socket中註冊了目標地址,則此函數只能接收目標地址發來的數據。
如果socket中的目標地址未註冊,或者註冊爲0.0.0.0::0,則表示此函數可以接收任意IP任意端口發來的數據;如果此socket的本機IP不爲0.0.0.0,則表示只會在指定的IP上進行監聽,如果本機IP指定爲0.0.0.0,則表示在本機的任意可用的IP上進行監聽。
在UDP客戶端中使用connect事先綁定目標地址還有一個好處,就是發送數據和接收數據可以不再使用sendto函數和recvfrom函數了,可以直接使用send和recv函數,或者使用write和read函數(linux下)。
最後,如何從一個socket文件描述符中獲取其所綁定的目標IP和本機IP? 函數getpeername可以獲取目標IP和目標端口; 函數getsockname可以獲取本socket所使用的IP和端口。
哎,還是相關知識太少,等後面學的深入一點,可能這些問題就根本不是啥問題了!
UDP的sendto過快導致發送失敗,應該怎麼辦?
UDP的sendto過快導致發送失敗,應該怎麼辦?在寫一個關於網絡多播的代碼時,sendto發送過快導致發送失敗,WSAGetLastError() 爲WSAEWOULDBLOCK,應該怎麼辦呢? 網…顯示全部