zoukankan      html  css  js  c++  java
  • Linux学习四:UDP编程(上)

    关于UDP和TCP对比优缺,这里就不说了。
      使用UDP代码所掉用的函数和用于TCP的函数非常类似,这主要因为套接口库在底层的TCP和UDP的函数上加了一层抽象,通过这层抽象使得编程更容易,但失去了一些控制。
      二者函数调用唯一的实际区别是soceket函数调用的一个参数,TCP的是SOCK_STREAM,UDP的是SOCK_DGRAM,二者都可以使用recvfrom函数,而recv只用于TCP。
      当然函数的变化不是这么简单,因为你要从一种有连接的协议转向到无连接的协议上去。
    这里写个很简单直接的UDP应用了解过程。实现一个启动向另一个系统的某个端口传输消息的程序,这个程序没有握手机制,也不确定另一个系统是否正在侦听、接受或处理数据。
      发送端:sender,发送文本消息,再发个终止消息(告诉接收方发送完毕)。

    UDP编程的客户端一般步骤是:

    1、创建一个socket,用函数socket();
    2、设置socket属性,用函数setsockopt();* 可选
    3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选
    4、设置对方的IP地址和端口等属性;
    5、发送数据,用函数sendto();
    6、关闭网络连接;
      sender.c :
          #include “stdio.h”只能用“”表示了,<显示不出来

          #include “stdlib.h”
          #include “string.h”
          #include “sys/socket.h”
          #include “netinet/in.h”
          #include “arpa/inet.h”
          #include “netdb.h”
      int port=6789;

          void main()
             {
               int socket_descriptor;// 定义套接口描述字
               int i=0;
               char buf[120];//设置缓冲区
               struct sockaddr_in address;//处理网络通信地址,把像xxx.xxx.xxx.xxx十进制

                                                  //的IP地址转化 为32位整数,失败返回INADDR_NONE

                  初始化Internet协议套接字地址结构
               bzero(&address,sizeof(address));//空数据结构
               address.sin_family=AF_INET;
               address.sin_addr.s_addr=inet_addr("127.0.0.1");//设置服务器的ip地址函数

               address.sin_port=htons(port);  //设置端口

               创建一个UDP套接字
               socket_descriptor=socket(AF_INET,SOCK_SGRAM,0);


              循环发送数据
               for(i=0;i<120;i++)
                 {
                   sprintf(buf,"data packet with ID %d ",i);
                   sendto(socket_descriptor,buf,sizeof(buf),0,
                               (struct sockaddr *)&address,sizeof(address));
                 }

            

              发送一个终止信息
                  sprintf(buf,"stop ");
               sendto(socket_descriptor,buf,sizeof(buf),0,
                           (struct sockaddr *)&address,sizeof(address));

              关闭网络
               close(socket_descriptor);
               printf("Message Sent,Terminating ");

               exit(0);
             }
    具体详细注释下:

    首先库文件:

                        stdlib.h:包含了C、C++语言的最常用的系统函数,定义了五种类型、一些宏和通用工具函数.

                                     常用的函数如malloc()、calloc()、realloc()、free()、ystem()、atoi()、atol()、rand()、

                                     srand()、exit()等等

                        string.h:字符数组的函数定义的头文件,常用函数有strlen、strcmp、strcpy等等

                sys/socket.h:提供socket函数及数据结构

                 netinet/in.h:定义数据结构sockaddr_in,互联网地址族

                  arpa/inet.h:提供IP地址转换函数

                       netdb.h:提供设置及获取域名的函数

    再看看涉及到的函数:

              struct sockaddr是通用的套接字地址,而struct sockaddr_in则是internet环境下套接字的地址形式,

    二者长度一样都是16个字节。二者是并列结构,指向sockaddr_in结构的指针也可以指向sockaddr。一般情况下,

    需要把sockaddr_in结构强制转换成sockaddr结构再传入系统调用函数中。

           inet_addr被linux下的inet_aton取代.函数作用是把作为参数的字符串转化为内部能够使用的一个

    作为因特网地址的整数.

             htons函数处理不同系统对内部的数据表示方法不同,使你的主机字节序和网络字节序匹配.

             socket函数创建套接字:0表示默认 socket函数,向系统申请一个通信端口SOCK_DGRAM 默认使用UDP
                                 调用socket函数时:

                                                    UDP使用SOCK_SGRAM,

                                                    TCPIP使用SOCK_STREAMA
                                                    AF_INET表示IPV4.

                                                    AF_INET6表示IPV6
                                                    AF_UNIX,AF_LOCAL表示本地通信
                                                    SOCK_STREAM: 提供面向连接的稳定数据传输,即TCP协议。
                                                 OOB: 在所有数据传送前必须使用connect()来建立连接状态。
                                                      SOCK_DGRAM: 使用不连续不可靠的数据包连接。
                                                          SOCK_SEQPACKET: 提供连续可靠的数据包连接。
                                                      SOCK_RAW: 提供原始网络协议存取。
                                                      SOCK_RDM: 提供可靠的数据包连接。
                                                  SOCK_PACKET: 与网络驱动程序直接通信。

             sendto函数通过套接口发送一个消息,在此使用了无连接的套接口:消息的发送目的地址由address指定。具体参数介绍不再说明。

             sprintf函数把格式化的数据写入某个字符串,返回值:字符串长度(strlen)例如:

             char* who = "I";
             char* whom = "csdn";
             sprintf(s, "%s love %s.", who, whom); //产生:"I love csdn. "  这字符串写到s中



            接收端:receiver


            receiver.c:

            #include “stdio.h”只能用“”表示了,<显示不出来

          #include “stdlib.h”
          #include “string.h”
          #include “sys/socket.h”
          #include “netinet/in.h”
          #include “arpa/inet.h”
          #include “netdb.h”

           
     int port=6789;
            void main()
             {
               int sin_len;
               char message[256];
               int socket_descriptor;
               struct sockaddr_in sin;
               printf("Waiting for data from sender ");
              
               bzero(&sin,sizeof(sin));
               sin.sin_family=AF_INET;
               sin.sin_addr.s_addr=htonl(INADDR_ANY);//htonl(将32位主机字符顺序

                                                                                      //转换成网络字符顺序)
               sin.sin_port=htons(port);//htons(将16位主机字符顺序转换成网络字符

                                                            //顺 序)
               sin_len=sizeof(sin);
     
               socket_descriptor=socket(AF_INET,SOCK_DGRAM,0);//建立一个端口
               bind(socket_descriptor,(struct sockaddr *)&sin,sizeof(sin));//将主机地址

                                                                                                             //与端口绑定
               while(1)
                  {
                     recvfrom(socket_descriptor,message,sizeof(message),0,
                                    (struct sockaddr *)&sin,&sin_len);//接受消息
                     printf("Response from server:%s ",message);
                     if(strnmcp(message,"stop",4)==0)//比较接受message和stop的前4个

                                                                             //字符。>返回大于1,=返回0。

                         {
                          printf("Sender has told me end connection ");
                          break;
                         }
                  }
                close(socket_descriptor);
                exit(0);
             }
    分别:gcc -o xxx xxx.c  注意:o是小写,大写的话会提示没有xxx文件或文件夹。
    然后分别在不同工作台运行:./xxx
    显示如下:

    Linux学习四:UDP编程(上)

    Linux学习四:UDP编程(上)

  • 相关阅读:
    在Linux下删除文件及文件夹(rm)
    修改Linux文件权限
    文件分页显示(ls -al |more)
    linux的文件权限
    Linux中的重启(reboot)
    linux关机前同步数据(sync)
    hdu4990 Reading comprehension 矩阵快速幂
    hdu4965 Fast Matrix Calculation 矩阵快速幂
    hdu4847 Wow! Such Doge! KMP
    hdu4705 Y 树形DP
  • 原文地址:https://www.cnblogs.com/samewang/p/4774172.html
Copyright © 2011-2022 走看看