1、編寫udp server程式的步驟
(1)使用socket()來建立乙個udp socket,第二個引數為sock_dgram。
(2)初始化sockaddr_in結構的變數,並賦值
這裡使用「2030」作為服務程式的埠,使用「inaddr_any」作為繫結的ip位址即任何主機上的位址。
(3)使用bind()把上面的socket和定義的ip位址和埠繫結。這裡檢查bind()是否執行成功,如果有錯誤就退出。這樣可以防止服務程式重複執行的問題。
(4)進入無限迴圈程式,使用recvfrom()進入等待狀態,直到接收到客戶程式傳送的資料,就處理收到的資料,並向客戶程式傳送反饋。這裡是直接把收到的資料發回給客戶程式。
2、srv.cpp程式內容
#include #include #include #include int main()
struct sockaddr_in srvaddr, clientaddr;
srvaddr.sin_family=af_inet;
srvaddr.sin_addr.s_addr=htonl(inaddr_any);
srvaddr.sin_port=htons(2030);
if(bind(srvsock, (struct sockaddr *)&srvaddr, sizeof(srvaddr))==-1)
socklen_t len=sizeof(srvaddr);
while(1)
;char sendmsg[128]=;
memcpy(sendmsg, "hello, client", 128);
recvfrom(srvsock, recvmsg, 128, 0, (struct sockaddr *)&clientaddr, &len);
printf("接收到資料%s\n", recvmsg);
sendto(srvsock, sendmsg, 128, 0, (struct sockaddr *)&clientaddr, len);
printf("傳送資料%s\n", sendmsg);
}return 0;
}
1、編寫udp client程式的步驟
(1)初始化sockaddr_in結構的變數,並賦值。
這裡使用「2030」作為連線的服務程式的埠,從命令列引數讀取ip位址,並且判斷ip位址是否符合要求。
(2)使用socket()來建立乙個udp socket,第二個引數為sock_dgram。
(3)使用connect()來建立與服務程式的連線。
與tcp協議不同,udp的connect()並沒有與服務程式三次握手。上面說了udp是非連線的,實際上也可以是連線的。使用連線的udp,kernel可以直接返回錯誤資訊給使用者程式,從而避免由於沒有接收到資料而導致呼叫recvfrom()一直等待下去,看上去好像客戶程式沒有反應一樣。
(4)向服務程式傳送資料,因為使用連線的udp,所以使用write()來替代sendto()。這裡的資料直接從標準輸入讀取使用者輸入。
(5)接收服務程式發回的資料,同樣使用read()來替代recvfrom()。
(6)處理接收到的資料,這裡是直接輸出到標準輸出上。
注意:
1. 在linux作業系統中,套接字可視為檔案,在呼叫connect()函式之後就可以呼叫read()和write()直接在其上進行接收和傳送。
2. 當用recvfrom()函式接收的時候並沒有錯誤提示,而當用read()函式讀取的時候有錯誤提示。原因尚未知。
client.cpp程式內容:
執行例子程式#include #include #include #include #include #include int main()
struct sockaddr_in destaddr;
destaddr.sin_family=af_inet;
destaddr.sin_addr.s_addr=inet_addr("127.0.0.1");
destaddr.sin_port=htons(2030);
socklen_t len=sizeof(destaddr);
connect(clientsock, (struct sockaddr *)&destaddr, len);
/*即便鏈結出錯,也不會返回任何資訊
if(connect(clientsock,(struct sockaddr *)&destaddr, len)==-1)
*/char sendmsg[128]=;
memcpy(sendmsg, "hello, server", 128);
char recvmsg[128]=;
/* 用sendto()和recvfrom()沒有鏈結錯誤提示
sendto(clientsock, sendmsg, 128, 0, (struct sockaddr *)&destaddr, len);
while(1)
;recvfrom(clientsock, recvmsg, 128, 0, (struct sockaddr *)&destaddr, &len);
printf("接收到資料%s\n", recvmsg);
break;}*/
write(clientsock, sendmsg, 128);
while(1)
recvmsg[n]=0;
printf("接收到資料%s\n", recvmsg);
break;
} }
1、編譯例子程式
使用如下命令來編譯例子程式:
gcc -wall -o srv srv.cpp
gcc -wall -o client client.cpp
編譯完成生成了udpserv和udpclient兩個可執行程式。
2、執行udp server程式
執行./srv &命令來啟動服務程式。我們可以使用netstat -ln命令來觀察服務程式繫結的ip位址和埠,部分輸出資訊如下:
active internet connections (only servers)
proto recv-q send-q local address foreign address state
udp 0 0 0.0.0.0:2030 0.0.0.0:*
可以看到udp處有「0.0.0.0:2030」的內容,說明服務程式已經正常執行,可以接收主機上任何ip位址且埠為2030的資料。
如果這時再執行./srv &命令,就會看到如下資訊:
繫結失敗:
address already in use
說明已經有乙個服務程式在執行了。
出現這種情況可以用命令kill結束正在執行的程式,並重新開啟。
3、執行udp client程式
執行./client 命令來啟動客戶程式,使用127.0.0.1來連線服務程式,執行效果如下:
接收到資料hello, client
輸入的資料都正確從服務程式返回了,按ctrl+c可以退出程式。
如果服務程式沒有啟動,而執行客戶程式,就會看到如下資訊:
read error: connection refused
說明指定的ip位址和埠沒有服務程式繫結,客戶程式就退出了。
這就是使用connect()的好處,注意,這裡錯誤資訊是在向服務程式傳送資料後收到的,而不是在呼叫connect()時。
如果使用tcpdump程式來抓包,會發現收到的是icmp的錯誤資訊。
Linux實現UDP連線
udp是無連線不可靠的ip協議,和tcp有所不同。udp伺服器呼叫socket bind listen 完成套接字初始化後,呼叫accept 阻塞等待處於監聽埠的狀態。udp客戶端呼叫socket 初始化後,呼叫connect 傳送syn欄位並阻塞等待應答。客戶端如果一直與服務端連線,服務端退出後重...
Linux下面的編譯和連線
編譯和連線 編譯通常是對單個原始檔進行編譯成.o檔案 要加上 c選項,比如 gcc o aa.o c aa.cpp 否則會提示找不到main函式 因為有些模組只是提供單元函式 並沒有main函式 編譯只檢查基本語法,對於引用的外部函式,只用能找到其宣告就可以正確編譯通過,比如在cpp檔案中包含了引用...
Linux下的UDP連線程式設計
udp是無連線不可靠的ip協議,和tcp有所不同。udp伺服器呼叫socket bind listen 完成套接字初始化後,呼叫accept 阻塞等待處於監聽埠的狀態。udp客戶端呼叫socket 初始化後,呼叫connect 傳送syn欄位並阻塞等待應答。客戶端如果一直與服務端連線,服務端退出後重...