UDP屬於非鏈接傳輸,所以不須要進行鏈接操做,直接可根據IP地址與端口發送數據服務器
服務器端:socket
char buf[1024]; int i=0; int fd = socket(AF_INET,SOCK_DGRAM,0); struct sockaddr_in dest_addr; bzero(&dest_addr,sizeof(dest_addr)); socklen_t addrlen; dest_addr.sin_family=AF_INET; dest_addr.sin_port=htons(10000); dest_addr.sin_addr.s_addr=INADDR_ANY; bind(fd,(struct sockaddr*)&dest_addr,sizeof(dest_addr)); while (1) { i++; int ret = recvfrom(fd, buf, 1024, 0,(struct sockaddr*) &dest_addr, &addrlen); if(ret < 0){ perror("recvfrom"); break; } printf ("%s,%d\n", inet_ntoa (dest_addr.sin_addr), i); //得到地址dest_addr後,可用sendto向服務器發送數據 } printf ("%s,%d\n", inet_ntoa (dest_addr.sin_addr), i);
服務器必須有固定的IP已經端口,所以必須使用bind函數把自身的套接字與固定端口綁定。函數
因爲服務器沒法得知客戶的IP以及端口,所以服務器必須首先使用UDP接收函數recvfrom()等待客戶端發送數據。當客戶端的數據到達後,客戶端的地址信息被記錄與dest_addr中,此時即可對客戶傳輸數據spa
客戶端:code
char buf[1024]; int i=0; struct sockaddr_in dest_addr; int sockfd = socket(AF_INET,SOCK_DGRAM,0); int len = sizeof(buf); bzero(&dest_addr,sizeof(dest_addr)); dest_addr.sin_family=AF_INET; dest_addr.sin_port=htons(10000); dest_addr.sin_addr.s_addr=inet_addr("127.0.0.1"); connect(sockfd,(struct sockaddr *)&dest_addr, sizeof(dest_addr));//如不鏈接,則系統爲客戶端隨機分配端口 while(i<10000) { i++; int ret = sendto(sockfd, buf, len, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); if (ret < 0) { perror("write error"); break; } } printf("send number:%d\n",i);
客戶端必須事先知道服務器的IP地址以及端口,才能使用UDP函數sento()對服務器發送數據。blog
客戶端不需綁定端口。如不適用connect()和bind()函數,則系統自動給客戶端隨機分配一個端口做爲發送端口使用,每次發送都使用不一樣的端口。如使用connect()設置後,則使用固定的端口發送數據。get
聊天室:不分服務器端和客戶端,只需指明對方的IP和端口就能夠聊天。string
#include <arpa/inet.h> #include <stdio.h> #include <string.h> #include <netinet/in.h> #include "pthread.h" char buf[1024]; int fd; //thread for receive msg void* receiver(void* p){ struct sockaddr_in dest_addr; int addrlen; while (1) { int ret = recvfrom(fd, buf, 1024, 0,(struct sockaddr*) &dest_addr, &addrlen); if(ret < 0) { perror("recvfrom"); break; } printf ("from %s:%d\n", inet_ntoa (dest_addr.sin_addr),ntohs(dest_addr.sin_port)); printf("%s\n",buf); } } //main thread for send msg int main(int argc,char **argv) { if(argc!=4){ printf("usage:order IP port_dest port_local\n"); return 0; } char buf[1024]; fd = socket(AF_INET,SOCK_DGRAM,0); struct sockaddr_in dest_addr,my_addr; bzero(&dest_addr,sizeof(dest_addr)); socklen_t addrlen; dest_addr.sin_family=AF_INET; dest_addr.sin_port=htons(atoi(argv[2])); dest_addr.sin_addr.s_addr=inet_addr(argv[1]); bzero(&my_addr,sizeof(my_addr)); my_addr.sin_family=AF_INET; my_addr.sin_port=htons(atoi(argv[3])); my_addr.sin_addr.s_addr=INADDR_ANY; bind(fd,(struct sockaddr*)&my_addr,sizeof(my_addr)); //init the thread pthread_t receiver_thread; if(0!=pthread_create(&receiver_thread, NULL, receiver, NULL)) printf("create thread failed\n"); while (1) { gets(buf); if(0==strcmp(buf,"exit")){ close(receiver_thread); break; } int ret = sendto(fd, buf, 1024, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); if (ret < 0){ perror("write error"); break; } } }
經過寫聊天室程序加深了對sendto和recvfrom兩個UDP函數用法的理解。it
sendto(fd, buf, 1024, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));fd是本身的套接字,而不是發送目標的套接字。fd經過connect()或bind()能夠與端口綁定,從而使用固定端口發送數據。如不適用此二函數,則使用隨機端口發送。只要dest_addr正確設置了接受方的IP地址以及端口,便可發送數據。io
recvfrom(fd, buf, 1024, 0,(struct sockaddr*) &dest_addr, &addrlen);fd也是本身的套接字,不是接收方的套接字。也不須要事先設置接收方的地址就能夠接受全部發送給本身的信息,dest_addr只是在接收到數據後記錄發送方的地址而已。