网络编程—简单的udp套接字编程(5)

6 篇文章 0 订阅
5 篇文章 0 订阅

这里写图片描述

从上面图片可以看出,在udp编程模型中,服务器端不需要设置监听的套接字,客户端中也不需要建立连接的过程。
客户端的模型中,也可以在创建socket之后调用connect函数,不过此时udp的connect作用和tcp中的connect不一样,udp中的connect只是将sockaddr信息设置到socket中去,后面调用sendto和recvfrom的函数可以改为tcp中的send和recv。
详情参见下面代码:

//客户端代码
#include <stdlib.h>
#include <unistd.h>
#include <resolv.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <time.h>
#include <string.h>
#include <signal.h>

const int MAXBUF=1000;

void sig_handler(int signo)
{
        if(signo == SIGINT)
        {
                printf("server close\n");
                exit(1);
        }
}

int main()
{
        // 第一个参数选用AF_INET表示选用ipv4,第二个参数选用SOCK_DGRAM(udp)
        int socketfd = socket(AF_INET, SOCK_DGRAM, 0);
        struct sockaddr_in dst;
        dst.sin_family = AF_INET;
        dst.sin_port = htons(10567);
        dst.sin_addr.s_addr = htonl(0x7f000001);
        int ret = 0;
        // 将sockaddr信息设置到socketfd中
        ret = connect(socketfd, (struct sockaddr*)&dst, sizeof(sockaddr_in));
        if(ret != 0)
        {
                printf("connect failed\n");
                close(socketfd);
                socketfd = -1;
        }
        char buf[MAXBUF] = {0};
        int i = 0;

        {
                memset(buf, 0, sizeof(buf));
                sprintf(buf, "i = %d, socket = %d, time = %lu", i, socketfd, clock());
                printf("send buffer = [%s]\n", buf);
                send(socketfd,  buf, strlen(buf), 0);
                memset(buf, 0, sizeof(buf));
                ret = recv(socketfd, buf, sizeof(buf), 0);
                if(ret == 0)
                {
                        printf("error find\n");
                        //break;
                }
                else
                {
                        printf("recv len = %d, i = %d, socket = %d,\n", ret, i, socketfd);
                        printf("recv buffer = [%s]\n", buf);
                }
        }
        close(socketfd);
        socketfd = -1;
        return 0;
}

服务器端代码:

#include <sys/socket.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>

const unsigned int MAXBUF = 1000;
int listenFd = -1;

// 信号处理函数
void sig_handler(int signo)
{
    // ctrl+c信号
        if(signo == SIGINT)
        {
                printf("server close\n");
                close(listenFd);
                listenFd = -1;
                exit(1);
        }
            //子进程结束信号
        if(signo == SIGCHLD)
        {
                printf("child process exit\n");
                wait(0);
        }
}

// 输出sockaddr信息
void out_addr(struct sockaddr_in *addr)
{
        if(addr == NULL)
        {
                printf("invalid param addr\n");
                return;
        }
        switch(addr->sin_family)
        {
                case AF_INET:
                        printf("AF_INET\n");
                        break;
                case AF_INET6:
                        printf("AF_INET6\n");
                        break;
                default:
                        printf("unknown\n");
                        break;
        }
        char ip[20] = {0};
        memset(ip, 0, sizeof(ip));
        //将ip地址转换成主机点分十进制
        inet_ntop(addr->sin_family, &addr->sin_addr, ip, sizeof(ip));
        printf("port = %d, ip = %s\n", ntohs(addr->sin_port), ip);

}

void do_service(int sockfd)
{
        struct sockaddr_in clientAddr;
        socklen_t len = sizeof(clientAddr);
        char buffer[MAXBUF] = {0};
        memset(buffer, 0, sizeof(buffer));
        if(recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&clientAddr, &len) < 0)
        {
                printf("recv failed\n");
                return;
        }
        else
        {
                out_addr(&clientAddr);
                printf("client send = [%s]\n", buffer);
                memset(buffer, 0, sizeof(buffer));
                long int t = time(0);
                char *ptr = ctime(&t);
                size_t size = strlen(ptr) * sizeof(char);
                if(sendto(sockfd, ptr, size, 0, (struct sockaddr*)&clientAddr, len) < 0)
                {
                        printf("send failed [%s]\n", buffer);
                }
                else
                {

                }
        }
}



int main()
{
        if(signal(SIGINT, sig_handler) == SIG_ERR)
        {
                perror("signal error\n");
                exit(1);
        }
        listenFd = socket(AF_INET, SOCK_DGRAM, 0);
        if(listenFd <= 0)
        {
                printf("create tcp socket failed\n");
                return -1;
        }

        int ret = 0;
        int opt = 1;
           //  设置地址重用
        if((ret = setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) < 0)
        {
                perror("setsockopt error\n");
                exit(1);
        }

        struct sockaddr_in local;
        local.sin_family = AF_INET;
        local.sin_port = htons(10567);
        local.sin_addr.s_addr = INADDR_ANY;// htonl(0x7f000001);
        ret = bind(listenFd, (struct sockaddr*)&local, sizeof(sockaddr));
        if(ret != 0)
        {
                printf("bind ret = %d\n", ret);
                return -2;
        }
        sockaddr_in src;
        unsigned int srcLength = sizeof(sockaddr_in);
        char buffer[MAXBUF] = {0};
        while(1)
        {
                do_service(listenFd);
        }
        close(listenFd);
        listenFd = -1;
        return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值