简单的UDP实现

根据UDP协议的特性,我们实现一个简单的回显服务器。

UDP协议:
传输层协议
无连接
不可靠
面向数据报

服务器代码:

   ///////////////                                                                                                                                        
   // UDP版本的服务器
   // 1.绑定端口号
   // 2.服务器7*24小时等待客户端发送的请求
   // 3.把响应发回客服端
   //////////////

#include
#include
#include
#include
#include
#include
#include

void service(int sock)
{
    char buf[128];
    for(;;)
    {
        //临时的sockaddr_in 结构体接收
        struct sockaddr_in peer;
        socklen_t len = sizeof(peer);
        buf[0] = 0;
        //接收客户端发来的数据   数据存在buf
        ssize_t s  = recvfrom(sock,buf,sizeof(buf)-1,\
                              0,(struct sockaddr*)&peer,&len);

        if(s > 0)
        {
            buf[s] = 0;
            //打印从哪个客户端接收到的数据
            printf("[%s,%d] # %s\n",inet_ntoa(peer.sin_addr),\
                            ntohs(peer.sin_port),buf);
            //把响应发送给客户端   buf
            sendto(sock,buf,strlen(buf),0,\
                   (struct sockaddr*)&peer,len);
        }
    }
}

 // ./server 0  8080
int main(int arg,char *argv[])
{
    if(arg != 3)
    {
        printf("usage: %s [ip] [port]\n",argv[0]);
        return 1;
    }
    //SOCK_DGRAM表示UDP ipv4: AF_INETET 
    int sock = socket(AF_INET,SOCK_DGRAM,0);
    if(sock < 0)
    {
        printf("socket error!\n");
        return 2;
    }
    //初始化sockaddr_in local    IPV4: AF_INET 
    struct sockaddr_in local;
    local.sin_family = AF_INET;
    local.sin_port = htons(atoi(argv[2]));
    //字符串IP地址 转换成 in_addr_t   :inet_addr() 看博主博客的地址转换函数的介绍
    local.sin_addr.s_addr = inet_addr(argv[1]);

    //绑定端口号
    if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0)
    {
        printf("bind error\n");
        return 3;
    }
    //业务  ---  回显
    service(sock);

    close(sock);
    return 0;
}

客户端代码:

 // UDP 版本的客户端
 // 1. 从标准输入, 读入一个字符串
 // 2. 把这个字符串通过 socket 发送给服务器
 // 3. 尝试从服务器读取响应数据
 // 4. 把响应结果写到标准输出上.
  ///////////////////////////////////////////////////////

#include
#include
#include
#include
#include
#include
#include

//client  127.0.0.1 8080

int main(int arg,char *argv[])
{
    if(arg != 3)
    {
        printf("usage: %s [ip] [port]\n",argv[0]);
        return 1;
    }
    //创建sock < 0 创建失败  SOCK_DGRAM表示UDP ipv4: AF_INETET 
    int sock = socket(AF_INET,SOCK_DGRAM,0);
    if(sock < 0)
    {
        printf("socket error\n");
        return 2;


    //初始化 sockaddr_in  ipv4: AF_INETET  
    struct sockaddr_in server;
    server.sin_family = AF_INET;
    //端口号:atoi 字符转换成数字
    server.sin_port = htons(atoi(argv[2]));
    //IP地址转换函数   ----看博主博客地址转换函数的介绍
    server.sin_addr.s_addr = inet_addr(argv[1]);
    socklen_t len = sizeof(server);

    //缓冲区
    char buf[128];

    //回显服务器,死循环
    for(;;)
    {
        buf[128] = 0;
        //从标准输入中读取存放在buf   sizeof(buf)-1 是为了最后为一个字节为0 
        ssize_t s = read(0,buf,sizeof(buf)-1);
        if(s>0)
        {
            buf[s-1] = 0;

            //发送数据
            sendto(sock,buf,strlen(buf),0,(struct sockaddr*)&server,len);
            //接受数据
            s = recvfrom(sock,buf,sizeof(buf)-1,0,NULL,NULL);
            if(s > 0)
            {
                buf[s] = 0;
                printf("server echo# %s\n",buf);
            }
        }
    }

    close(sock);
    return 0;
}

运行结果:
client:
简单的UDP实现_第1张图片

server:
简单的UDP实现_第2张图片

ps:

发送函数:
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                      const struct sockaddr *dest_addr, socklen_t addrlen);

sockfd: socket
const void *buf: 缓冲区地址
size_t len:缓冲区的大小,buf的大小
int flags: 0
const struct sockaddr *dest_addr,结构体的地址
socklen_t addrlen : 结构体大小


接收函数:
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen);

int sockfd:socket 
void *buf:缓冲区地址
size_t len:缓冲区大小
int flags:0
struct sockaddr *src_addr:结构体地址
socklen_t *addrlen:结构体大小

你可能感兴趣的:(网络)