zoukankan      html  css  js  c++  java
  • Linux 网络编程详解十二

    UDP的特点
    --无连接
    --基于消息的数据传输服务
    --不可靠
    --UDP更加高效
    UDP注意点
    --UDP报文可能会丢失,重复
    --UDP报文可能会乱序
    --UDP缺乏流量控制(UDP缓冲区写满之后,没有流量控制,会覆盖缓冲区)
    --UDP协议数据报文截断(如果接收到的数据报文大于缓冲区,报文可以被截断,后面部分丢失)
    --recvfrom返回0,不代表连接关闭(实际上UDP是无连接的),sendto可以发送数据0包,只含有UDP头部
    --UDP客户端也可以调用connect,但是并没有完成三次握手,只是维护了一个状态信息(和对等方的)
    --一旦调用了connect,就可以使用send函数
    //UDP协议客户端
    #define SETNO 0
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <errno.h>
    #include <sys/types.h>          /* See NOTES */
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <termios.h>
    
    /**
     * clear_back - 退格不回显
     * 成功返回0,失败返回-1
     * */
    int clear_back()
    {
        struct termios term;
        memset(&term, 0, sizeof(term));
        //获取当前系统设置
        if (tcgetattr(STDIN_FILENO, &term) == -1)
        {
            perror("tcgetattr() err");
            return -1;
        }
        //修改系统设置
        term.c_cc[VERASE] = '';
        //立即生效
        if (tcsetattr(STDIN_FILENO, TCSANOW, &term) == -1)
        {
            perror("tcgetattr() err");
            return -1;
        }
        return 0;
    }
    
    int main(int arg, char *args[])
    {
        if(clear_back()!=0)
            return -1;
        int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (sockfd == -1)
        {
            perror("socket() err");
            return -1;
        }
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(8080);
        //连接的服务器地址
        addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    #if SETNO==0
        /*
         * UDP客户端也可以调用connect,但是并没有完成三次握手,
         * 只是维护了一个状态信息(和对等方的),所以发送报文时,不需要传服务器ip*/
         if(connect(sockfd,(struct sockaddr *)&addr,sizeof(addr))==-1)
         {
         perror("connect() err");
         return -1;
         }
    #endif
        char buf[1024] = { 0 };
        int rc = 0;
        while (fgets(buf, 1024, stdin) != NULL)
        {
    #if SETNO==0
            rc = send(sockfd, buf,strlen(buf),0);
    #else
            rc = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *) &addr,
                            sizeof(addr));
    #endif
    
            if (rc == -1)
            {
                perror("sendto() err");
                break;
            }
            memset(buf, 0, 1024);
            rc = recvfrom(sockfd, buf, 1024, 0, NULL, NULL);
            if (rc == -1)
            {
                perror("recvfrom() err");
                break;
            }
            fputs(buf, stdout);
            memset(buf, 0, 1024);
        }
        return 0;
    }
    //UDP协议服务器端
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <errno.h>
    #include <sys/types.h>          /* See NOTES */
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    
    int main(int arg, char *args[])
    {
        int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (sockfd == -1)
        {
            perror("socket() err");
            return -1;
        }
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(8080);
        //绑定本地IP地址
        addr.sin_addr.s_addr = inet_addr("127.0.0.1");
        if (bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
        {
            perror("bind() err");
            return -1;
        }
        int rc = 0;
        char buf[1024] = { 0 };
        struct sockaddr_in peeraddr;
        socklen_t peerlen = sizeof(peeraddr);
        while (1)
        {
            memset(buf,0,sizeof(buf));
            do
            {
                rc = recvfrom(sockfd, buf, 2, 0, (struct sockaddr *) &peeraddr,
                        &peerlen);
            } while (rc == -1 && errno == EINTR);
            if (rc == -1)
            {
                perror("recvfrom() err");
                break;
            }
            //fputs()函数必须以'
    '结尾才会打印在终端上,,否则需要清空缓冲区
            fputs(buf, stdout);
            fflush(stdout);
            //发送数据
            rc = sendto(sockfd, buf, rc, 0, (struct sockaddr *) &peeraddr,
                    sizeof(peeraddr));
            if (rc == -1)
            {
                perror("sendto() err");
                break;
            }
        }
        return 0;
    }
    .SUFFIXES:.c .o
    CC=gcc
    SRCS=hello.c
    OBJS=$(SRCS:.c=.o)
    EXEC=ser
    SRCS1=tec01.c
    OBJS1=$(SRCS1:.c=.o)
    EXEC1=clt
    
    start:$(OBJS) $(OBJS1)
        $(CC) -o $(EXEC) $(OBJS)
        $(CC) -o $(EXEC1) $(OBJS1)
        @echo "^_^-----OK------^_^"
    .c.o:
        $(CC) -Wall -g -o $@ -c $<
    clean:
        rm -f $(OBJS)
        rm -f $(EXEC)
  • 相关阅读:
    android 属性动画
    android EventBus
    android gson使用
    Date、String、Calendar类型之间的转化
    2020-08-26:裸写算法:树的非递归先序遍历。
    2020-08-25:BloomFilter的原理以及Zset的实现原理。
    2020-08-24:什么是小文件?很多小文件会有什么问题?很多小文件怎么解决?(大数据)
    2020-08-23:描述HTTPS和HTTP的区别。
    2020-08-22:I/O多路复用中select/poll/epoll的区别?
    2020-08-21:网络IO模型有哪些?
  • 原文地址:https://www.cnblogs.com/zhanggaofeng/p/6183658.html
Copyright © 2011-2022 走看看