socket程式設計UDP協議以及注意事項
阿新 • • 發佈:2018-11-01
//伺服器 #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define ERR_EXIT(m) \ do \ { \ perror(m); \ exit(EXIT_FAILURE);\ }while(0) void echo_srv(int sock) { char recvbuf[1024] = {0}; struct sockaddr_in peeraddr;//存放對方地址 socklen_t peerlen; int n; while(1) { peerlen= sizeof(peeraddr); //n為接收的資料位元組數 n=recvfrom(sock, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*)&peeraddr, &peerlen); if(n==-1) { if(errno==EINTR) continue; ERR_EXIT("recvfrom"); } else if(n>0) { fputs(recvbuf,stdout); sendto(sock, recvbuf, n, 0, (struct sockaddr*)&peeraddr, &peerlen); memset(recvbuf,0, sizeof(recvbuf)); } } close(sock); } int main(void) { int sock; if((sock = socket(PF_INET, SOCK_DGRAM, 0))<0)//繫結UDP協議 ERR_EXIT("socket"); //設定自己的地址為主機的任意地址 struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(5188); servaddr.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(sock, (struct sockaddr*)&servaddr, sizeof(servaddr))<0) ERR_EXIT("bind"); echo_srv(sock); return 0; } //客戶端 #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define ERR_EXIT(m) \ do \ { \ perror(m); \ exit(EXIT_FAILURE);\ }while(0) void echo_cli(int sock) { //設定接收方地址 struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(5188); servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //當伺服器未開啟時,客戶端傳送資料,則客戶端會收到ICMP錯誤應答, //本來是sendto未檢測,就傳送,造成recvfrom未能接收資料,也不能檢測錯誤,形成非同步錯誤 //connnect用於解決非同步錯誤,則recvfrom可以返回連線錯誤 //connect在此僅僅是維護與對等方一種狀態,連線一個遠端地址,使套接字只能向該地址傳送資料,則後邊的sendto就不用繫結地址了 connect(sock, (struct sockaddr*)&servaddr, sizeof(servaddr)); int ret; char sendbuf[1024] = {0}; char recvbuf[1024] ={0}; while(fgets(sendbuf, sizeof(sendbuf), stdin) != NULL) { sendto(sock, sendbuf, strlen(sendbuf), 0, (struct sockaddr*)&servaddr, sizeof(servaddr)); ret = recvfrom(sock, recvbuf, sizeof(recvbuf), 0, NULL, NULL);//接收資料,對方地址不知 if(ret == -1) { if(errno == EINTR) continue; ERR_EXIT("recvfrom"); } fputs(recvbuf,stdin); memset(sendbuf, 0, sizeof(sendbuf)); memset(recvbuf, 0, sizeof(recvbuf)); } } int main(void) { int sock; if((sock=socket(PF_INET, SOCK_DGRAM, 0))<0) ERR_EXIT("socket"); echo_cli(sock); return 0; }