[linux-socket]UNIX網絡編程之UDP鏈接

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只是在接收到數據後記錄發送方的地址而已。

相關文章
相關標籤/搜索