[linux-socket]UNIX网络编程之UDP连接

UDP属于非连接传输,因此不需要进行连接操作,直接可根据IP地址与端口发送数据

服务器端

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中,此时便可对客户传输数据

客户端:

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()对服务器发送数据。

客户端不需绑定端口。如不适用connect()和bind()函数,则系统自动给客户端随机分配一个端口作为发送端口使用,每次发送都使用不同的端口。如使用connect()设置后,则使用固定的端口发送数据。

聊天室:不分服务器端和客户端,只需指明对方的IP和端口就可以聊天。

#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函数用法的理解。

sendto(fd, buf, 1024, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));fd是自己的套接字,而不是发送目标的套接字。fd通过connect()或bind()可以与端口绑定,从而使用固定端口发送数据。如不适用此二函数,则使用随机端口发送。只要dest_addr正确设置了接受方的IP地址以及端口,即可发送数据。

recvfrom(fd, buf, 1024, 0,(struct sockaddr*) &dest_addr, &addrlen);fd也是自己的套接字,不是接收方的套接字。也不需要事先设置接收方的地址就可以接受所有发送给自己的信息,dest_addr只是在接收到数据后记录发送方的地址而已。

posted @ 2013-06-26 20:08  iyjhabc  阅读(649)  评论(0编辑  收藏  举报