曲径通幽论坛

标题: 简单 UDP 点对点通信实例 [打印本页]

作者: beyes    时间: 2010-4-3 16:04
标题: 简单 UDP 点对点通信实例
程序说明
程序使用 AF_INET 协议实现 UDP 点对点通信,即数据传输方式为 UDP 数据报方式,主要功能是发送端向接收端发送一条 "hello world“ 消息。使用时,接收端先运行。

接收端源码
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdlib.h>
#include <arpa/inet.h>

int main (int argc, char **argv)
{
    struct sockaddr_in s_addr;
    struct sockaddr_in c_addr;

    int sock;
    int len;
    char buff[128];
    socklen_t addr_len;
       
        /*建立 socket 对象,第 2 个参数表明使用的是 UDP 数据报*/
    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
        perror ("socket");
        exit (errno);
    } else
        printf ("create socket successfully\n");

    memset (&s_addr, 0, sizeof (struct sockaddr_in));

    s_addr.sin_family = AF_INET;
    s_addr.sin_port = htons (8888);   /*通过 8888 端口进行通信*/
    s_addr.sin_addr.s_addr = INADDR_ANY/*绑定再任何网口上*/

    if ((bind(sock, (struct sockaddr *)&s_addr, sizeof(s_addr))) == -1) {
        perror ("bind");
        exit (errno);
    } else
        printf ("bind address to socket. \n\r");

    addr_len = sizeof (c_addr);
   
    while (1) {
        len = recvfrom (sock, buff, sizeof(buff) - 1, 0,
                (struct sockaddr *)&c_addr, &addr_len);

        if (len < 0) {
            perror ("recvfrom");
            exit (errno);
        }
                /*接收到的字符串数据不包含 '\0',在这里添加上*/
        buff[len] = '\0';
        printf ("recive come from %s:%d message:%s\n\r",
                inet_ntoa (c_addr.sin_addr),ntohs (c_addr.sin_port), buff);

    }

    return (0);
}

发送端源代码
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdlib.h>
#include <arpa/inet.h>

int main (int argc, char **argv)
{
    struct sockaddr_in s_addr;
    int sock;
    int addr_len;
    int len;
    char buff[128];

    if ((sock = socket (AF_INET, SOCK_DGRAM, 0)) == -1) {
        perror ("socket");
        exit (errno);
    } else
        printf ("create socket. \n\r");

    s_addr.sin_family = AF_INET;
    s_addr.sin_port = htons(8888);
   
    if (argv[1])    /*在命令行中需要填写IP参数*/
        s_addr.sin_addr.s_addr = inet_addr (argv[1]);
    else {
        printf ("input server ip!\n");
        exit (0);
    }

    addr_len = sizeof (s_addr);
    strcpy (buff, "hello world");

    len = sendto (sock, buff, strlen(buff), 0, (struct sockaddr *)&s_addr, addr_len);

    if (len < 0) {
        printf ("\n\rsend error.\n\r");
        return (3);
    }

    printf ("send successfully.\n\r");

    return (0);
}

运行与输出
接收端先运行:
./udp_rev
create socket successfully
bind address to socket.
发送端发送数据:
./udp_send 127.0.0.1
create socket.
send successfully.
在发送端发送数据后,可以看到服务器端有输出:
recive come from 127.0.0.1:58888 message:hello world

程序说明
接收端使用 bind() 函数显式的绑定了自己的 IP 信息和端口信息,此端口也是发送端程序向接收端发起连接时指定的接收端端口。接收端使用的 recvfrom() 是阻塞式接收方式,也就是说如果没有发送数据,接收端就会被阻塞而等待。

发送端并没有再程序中显式的绑定自己的信息,但系统为其完成这一操作,也就是系统自己随机为发送端指定了一个端口用以发送,所以接收端显示的端口信息并不是每次都是一样的,接收端发送数据使用 sendto() 函数。

接收端所用的 inet 的两个函数:
inet_ntoa() 和 ntohs() 见:http://www.groad.net/bbs/read.php?tid-955.html




欢迎光临 曲径通幽论坛 (http://www.groad.net/bbs/) Powered by Discuz! X3.2