udp通信linux代码_linux udp通信代码 - CSDN
  • Linux下的udp通信

    热门讨论 2020-07-30 23:32:36
    Linuxudp通信程序,含客户端和服务器以及Makefile
  • linux---UDP代码通信

    2019-06-02 16:09:06
    udp连接特性: 无连接:可以不构成连接就进行通信 不可靠:数据并不能保证可靠性...udp通信流程 c++封装udp接口,封装接口便于我们更好的实现 1 /* 2 *udp的封装接口 3 */ 4 #include <iostream> 5 #i...

    udp连接特性

    • 无连接:可以不构成连接就进行通信
    • 不可靠:数据并不能保证可靠性
    • 面向数据报:每条数据有长度限制,整条数据发送整条数据接受,传输不灵活,但是不会存在粘包问题。
      原理在网络版块讲解
      udp通信流程
      在这里插入图片描述

    c++封装udp接口,封装接口便于我们更好的实现

      1 /*
      2  *udp的封装接口
      3  */
      4 #include <iostream>
      5 #include <string>
      6 #include <stdio.h>
      7 #include <unistd.h>
      8 #include <sys/socket.h>
      9 #include <errno.h>
     10 #include <stdlib.h>
     11 #include <netinet/in.h>
     12 #include <arpa/inet.h>
     13 
     14 class UdpSocket{
     15 public:
     16     UdpSocket():_socket(-1){
     17     };
     18     ~UdpSocket(){
     19     };
     20     //创建socket
     21     bool Socket(){
     22         _socket = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
     23         if(_socket < 0){
     26         }
     27         return true;
     28     }
     29     //绑定连接
     30     bool Bind(std::string ip,uint16_t port){
     31         struct sockaddr_in addr;
     32         addr.sin_family = AF_INET;
     33         addr.sin_port = htons(port);
     34         addr.sin_addr.s_addr = inet_addr(ip.c_str());
     35 
     36         int len = sizeof(addr);
     37 
     38         int ret = bind(_socket,(struct sockaddr*)&addr,len);
     39         if(ret < 0){
     40             perror("bind error\n");
     41             return false;
     42         }
     43         return true;
     44     }
     45     //接受数据
     46     bool Recv(std::string &buf,struct sockaddr_in *saddr){
     47         //*daddr是发送的ip信息
     48         //  ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
     49         //  struct sockaddr *src_addr, socklen_t *addrlen);
     50         char temp[1500];
     51         socklen_t len = sizeof(struct sockaddr_in);
     53         if(ret < 0){
     54             perror("recvfrom error\n");
     55             return false;
     56         }
     57         buf.assign(temp,ret);
     58         return true;
     59     }
     60     //发送数据
     61     bool Send(std::string& str,struct sockaddr_in* daddr){
     62     //  ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
     63     //  const struct sockaddr *dest_addr, socklen_t addrlen);
     64         int len = sizeof(struct sockaddr_in);
     65         int ret = sendto(_socket,str.c_str(),str.size(),0 
     66                 ,(struct sockaddr*)daddr,len);
     67         if(ret < 0){
     68             perror("sendto error\n");
     69             return false;
     70         }
     71         return true;
     72     }
     73     //关闭连接
     74     bool Close(){
     75         close(_socket);
     76         _socket = -1;
     77     }
     78     private:
     79     int  _socket;
     80 }; 
    

    udp服务端的实现

    4 #include "udpsocket.hpp"
      5 #define CHECK(T) if(!T) {return -1;}
      6 int main(int argc,char* argv[]){
      1 /*
      2  *实现udp服务器端
      3  */
      4 #include "udpsocket.hpp"
      5 #define CHECK(T) if(!T) {return -1;}
      6 int main(int argc,char* argv[]){
      7     //将我们的ip地址通过参数进行传递
      8     if(argc < 3){
      9         perror("./a.out ip port\n");
     10         return -1;
     11     }
     12     std::string ip = argv[1];//ip地址的信息
     13     uint16_t port = atoi(argv[2]);//port端口信息
     14     //创建封装的类
     15     UdpSocket sock;
     16     //创建我们的套接字
     17     CHECK(sock.Socket());
     18     //绑定
     19     CHECK(sock.Bind(ip,port));
     20     while(1){
     21         //接受数据
     22         std::string str;
     23         struct sockaddr_in client_addr;
     24         CHECK(sock.Recv(str,&client_addr));
     25         std::cout<<"client said:"<<str<<std::endl;
     26         std::string answer;
     27         std::cout<<"server say:";
     28         fflush(stdout);
     29         std::cin>>answer;
     30         CHECK(sock.Send(answer,&client_addr));
     31     }
     32     sock.Close();
     33     return 0;
     34 }  
    

    udp客户端代码实现

      1 /*
      2  udp客户端程序实现
      3  */
      4 #include "udpsocket.hpp"
      5 
      6 #define CHECK(T) if(!T) {return -1;}
      7 int main(int argc,char* argv[]){
      8     if(argc < 3){
      9         perror("./a.out ip port\n");
      1 /*
      2  udp客户端程序实现
      3  */
      4 #include "udpsocket.hpp"
      5 
      6 #define CHECK(T) if(!T) {return -1;}
      7 int main(int argc,char* argv[]){
      8     if(argc < 3){
      9         perror("./a.out ip port\n");
     10         return -1;
     11     }
     12     std::string ip = argv[1];
     13     uint16_t port = atoi(argv[2]);
     14 
     15     UdpSocket sock;
     16     //创建套接字
     17     CHECK(sock.Socket());
     18     //客户端不用创建连接,绑定的是绑定的服务器端的地址信息
     19     struct sockaddr_in ser_addr;
     20     ser_addr.sin_family = AF_INET;
     21     ser_addr.sin_port = htons(port);
     22     ser_addr.sin_addr.s_addr = inet_addr(ip.c_str());
     23     
     24     while(1){
     25         //发送数据
     26         std::string str;
     27         std::cout<<"client say:";
     28         fflush(stdout);
     29         std::cin>>str;
     30         CHECK(sock.Send(str,&ser_addr));
     31         std::string answer;
     32         CHECK(sock.Recv(answer,&ser_addr));
     33         std::cout<<"server said:"<<answer<<std::endl;
     34     }
     35     sock.Close();
     36     return 0;
     37 }  
    
    展开全文
  • Linux下的UDP通信

    2014-08-27 16:58:08
    Linux下的UDP通信 [日期:2012-06-02] 来源:Linux社区 作者:htttw [字体:大 中 小] 今天我们介绍如何编写Linux下的UDP程序,关于TCP程序可以参考这里:...

    Linux下的UDP通信

    [日期:2012-06-02] 来源:Linux社区  作者:htttw [字体:  ]

    今天我们介绍如何编写Linux下的UDP程序,关于TCP程序可以参考这里:http://www.linuxidc.com/Linux/2012-06/61802.htm

    由于UDP通信不需要事先建立连接,因此不需要TCP中的connect函数。

    服务器端的步骤如下:

    1. socket:      建立一个socket

    2. bind:          将这个socket绑定在某个端口上(AF_INET)

    3. recvfrom:  如果没有客户端发起请求,则会阻塞在这个函数里

    4. close:        通信完成后关闭socket

    客户端的步骤如下:

    1. socket:      建立一个socket

    2. sendto:     相服务器的某个端口发起请求(AF_INET)

    3. close:        通信完成后关闭socket


    可以看到,和TCP相比,步骤少了一些。


    这里我们用到了两个新的函数:

    int recvfrom(int sockfd, void * buf, size_t len, int flags, struct sockaddr * src_addr, socklen_t * addrlen);

    int sendto(int sockfd, const void * buf, size_t len, int flags, const struct sockaddr * dest_addr, socklen_t addrlen);


    recvfrom用于接收数据,sendto用于发送数据


    recvfrom:

    socket:socket套接字

    buf:接收到的数据的存放位置

    flags:一般情况下为0

    src_addr:接收的源地址

    addrlen:地址长度


    sendto:

    socket:socket套接字

    buf:要发送的数据的起始地址

    flags:一般情况下为0

    dest_addr:发送到的目的地址

    addrlen:地址长度

     

    还是先上代码:

    Makefile:

    1. all: server.c client.c  
    2.     gcc -Wall client.c -o client  
    3.     gcc -Wall server.c -o server  
    4.   
    5. clean:  
    6.     rm -rf *.o client server  
    展开全文
  • //服务器端 #include /* See NOTES */ #include #include #include #include #include #include #include #include /* socket  * bind  * sendto/recvfrom ...#define SER

    //服务器端

    #include <sys/types.h>          /* See NOTES */
    #include <sys/socket.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <signal.h>




    /* socket
     * bind
     * sendto/recvfrom
     */


    #define SERVER_PORT 8888


    int main(int argc, char **argv)
    {
    int iSocketServer;
    int iSocketClient;
    struct sockaddr_in tSocketServerAddr;
    struct sockaddr_in tSocketClientAddr;
    int iRet;
    int iAddrLen;


    int iRecvLen;
    unsigned char ucRecvBuf[1000];


    int iClientNum = -1;

    iSocketServer = socket(AF_INET, SOCK_DGRAM, 0);
    if (-1 == iSocketServer)
    {
    printf("socket error!\n");
    return -1;
    }


    tSocketServerAddr.sin_family      = AF_INET;
    tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short */
      tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
    memset(tSocketServerAddr.sin_zero, 0, 8);

    iRet = bind(iSocketServer, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));
    if (-1 == iRet)
    {
    printf("bind error!\n");
    return -1;
    }




    while (1)
    {
    iAddrLen = sizeof(struct sockaddr);
    iRecvLen = recvfrom(iSocketServer, ucRecvBuf, 999, 0, (struct sockaddr *)&tSocketClientAddr, &iAddrLen);
    if (iRecvLen > 0)
    {
    ucRecvBuf[iRecvLen] = '\0';
    printf("Get Msg From %s : %s\n", inet_ntoa(tSocketClientAddr.sin_addr), ucRecvBuf);
    }
    }

    close(iSocketServer);
    return 0;
    }








    //客报端

    #include <sys/types.h>          /* See NOTES */
    #include <sys/socket.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <stdio.h>


    /* socket
     * connect
     * send/recv
     */


    #define SERVER_PORT 8888


    int main(int argc, char **argv)
    {
    int iSocketClient;
    struct sockaddr_in tSocketServerAddr;

    int iRet;
    unsigned char ucSendBuf[1000];
    int iSendLen;
    int iAddrLen;


    if (argc != 2)
    {
    printf("Usage:\n");
    printf("%s <server_ip>\n", argv[0]);
    return -1;
    }


    iSocketClient = socket(AF_INET, SOCK_DGRAM, 0);


    tSocketServerAddr.sin_family      = AF_INET;
    tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short */
      //tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
      if (0 == inet_aton(argv[1], &tSocketServerAddr.sin_addr))
      {
    printf("invalid server_ip\n");
    return -1;
    }
    memset(tSocketServerAddr.sin_zero, 0, 8);


    #if 0
    iRet = connect(iSocketClient, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));
    if (-1 == iRet)
    {
    printf("connect error!\n");
    return -1;
    }
    #endif


    while (1)
    {
    if (fgets(ucSendBuf, 999, stdin))
    {
    #if 0
    iSendLen = send(iSocketClient, ucSendBuf, strlen(ucSendBuf), 0);
    #else
    iAddrLen = sizeof(struct sockaddr);
    iSendLen = sendto(iSocketClient, ucSendBuf, strlen(ucSendBuf), 0,
                         (const struct sockaddr *)&tSocketServerAddr, iAddrLen);


    #endif
    if (iSendLen <= 0)
    {
    close(iSocketClient);
    return -1;
    }
    }
    }

    return 0;
    }


    展开全文
  • Linux下TCP,UDP以及广播与多播通信代码大全)

    千次阅读 多人点赞 2013-02-01 10:34:45
    TCP、UDP、广播、多播的客户端服务器代码链接地址为(for free): tcp代码:http://download.csdn.net/detail/huangminqiang201209/4860661 udp代码:http://download.csdn.net/detail/huangminqiang201209/4860665...

    TCP、UDP、广播、多播的客户端服务器代码链接地址为(for free):

    tcp代码:http://download.csdn.net/detail/huangminqiang201209/4860661
    udp代码:http://download.csdn.net/detail/huangminqiang201209/4860665
    广播代码:http://download.csdn.net/detail/huangminqiang201209/4860672
    多播代码:http://download.csdn.net/detail/huangminqiang201209/4860719

     

        此文主要还是在于上面的代码,我这段时间因为要构建一个TCP服务器,所以就把socket这块完整的熟悉了一下,以下这些整理的比较随意,还望见谅哦吐舌头

    TCP

        Transmission Control Protocol 传输控制协议TCP是一种面向连接(连接导向)的、可靠的、基于字节流的运输层(Transport layer)通信协议,由IETF的RFC 793说明(specified)。在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能,UDP是同一层内另一个重要的传输协议。  
         在因特网协议族(Internet protocol suite)四层协议中,TCP层是位于IP层之上,应用层之下的传输层。不同主机的应用层之间经常需要可靠的、像管道一样的连接,但是IP层不提供这样的流机制,而是提供不可靠的包交换。  

     

    UDP
         UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是 OSI 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,IETF RFC 768是UDP的正式规范。

     

    广播

         广播和多播仅应用于UDP,它们对需将报文同时传往多个接收者的应用来说十分重要。TCP是一个面向连接的协议,它意味着分别运行于两主机(由IP地址确定)内的两进程(由端口号确定)间存在一条连接。
        考虑包含多个主机的共享信道网络如以太网。每个以太网帧包含源主机和目的主机的以太网地址(48 bit)。通常每个以太网帧仅发往单个目的主机,目的地址指明单个接收接口,因而称为单播(unicast)。在这种方式下,任意两个主机的通信不会干扰网内其他主机(可能引起争夺共享信道的情况除外)。然而,有时一个主机要向网上的所有其他主机发送帧,这就是广播。通过ARP和RARP可以看到这一过程。多播(multicast) 处于单播和广播之间:帧仅传送给属于多播组的多个主机。

     

    多播

        多播数据仅由对该数据报感兴趣的接口接收,也就是说,由运行希望参加多播会话应用系统的主机上的接口接收。广播一般局限与局域网,而多播既可用于局域网,也可用于广域网。
    IP多播提供两类服务:
        1) 向多个目的地址传送数据。有许多向多个接收者传送信息的应用:例如交互式会议系统和向多个接收者分发邮件或新闻。如果不采用多播,目前这些应用大多采用TCP来完成(向每个目的地址传送一个单独的数据复制)。然而,即使使用多播,某些应用可能继续采用TCP来保证它的可靠性。
        2) 客户对服务器的请求。例如,无盘工作站需要确定启动引导服务器。目前,这项服务是通过广播来提供的,但是使用多播可降低不提供这项服务主机的负担。

     

    函数

    1.socket 函数
       指定期望的通信协议类型。
    #include <sys/types.h> /* See NOTES */
    #include <sys/socket.h>

     int socket(int domain, int type, int protocol);
            返回:若成功则为非负描述符,出错则为-1。

    参数说明:
     domain:   指明协议族,也称为协议域,是一个常值。
               AF_INET              IPv4 协议
               AF_INET6             IPv6 协议
               AF_LOCAL/AF_UNIX       Unix协议域
               AF_ROUTE                 路由套接字
               AF_KEY                   密匙套接字
        
     type:    指明套接字的类型。
               SOCK_STREAM             字节流套接字(TCP)
               SOCK_DGRAM             数据报套接字(UDP)
               SOCK_SEQPACKET        有序分组套接字
               SOCK_RAW               原始套接字
       
     protocol: 指明协议类型。一般为0,以选择给定的domain和type组合的系统默认值。
               IPPROTO_TCP           TCP传输协议
               IPPROTO_UDP           UDP传输协议
               IPPROTO_SCTP          SCTP传输协议
    函数描述:
        socket 函数在成功时返回一个小的非负整数值,与文件描述符类似,我们称它为套接字描述符,简称 sockfd。为了得到这个套接字描述符,我们只是指定了协议族(IPv4、IPv6
        或Unix)和套接字类型(字节流、数据报或原始套接字)。我们并没有指定本地跟远程的协议地址。
        
    2.bind 函数    
       将一个本地协议地址赋予一个套接字。对于网际网协议,协议地址是32位的IPv4地址和128位的IPv6地址与16位的TCP或UDP端口号的组合。bind 函数主要用于服务器端,用来指定本地
       主机的哪个网络接口(IP,可以是INADDR_ANY,表示本地主机的任一网络接口)可以接受客户端的请求,和指定端口号(即开启的等待客户来连接的进程)。
     
    #include <sys/socket.h>
     int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);
             返回:若成功则为0,出错则为-1。

    参数说明:
        sockfd:          socket 函数返回的套接字描述符。
        myaddr、addrlen:指向一个套接字地址结构的指针和该结构的大小。

     struct sockaddr结构说明如下:
         struct sockaddr_in {
       short int sin_family;   /* 地址族 */
       unsigned short int sin_port;  /* 端口号 */
       struct in_addr sin_addr;   /* IP地址 */
       unsigned char sin_zero[8];  /* 填充0 以保持与struct sockaddr同样大小 */
         };

    函数描述:
        对于 TCP ,调用 bind 函数可以指定一个端口号,或指定一个IP地址,也可以两者都指定,还可以两者都不指定。
        服务器在启动时捆绑它们众所周知的端口号(如何捆绑?)。如果一个TCP客户或服务器未曾调用bind捆绑一个端口,当调用 connect 或 listen 时,内核就要为相应的套接字选择一个临时端口。
        让内核来选择临时端口对于TCP客户来说是正常的,除非应用需要一个预留端口。然而对于TCP服务器来说却极为罕见,因为服务器是通过它们的众所周知的端口号来被大家认识的。
     
        进程可以把一个特定的IP捆绑到它的套接字上,不过这个IP地址必须属于其所在主机的网络接口之一(对于TCP服务器)。对于TCP客户,这就为在该套接字上发送的IP数据报指派了源IP地址(服务器源地址)。对于TCP服务器,这就限定该套接字只接收那些目的地为这个IP地址的客户连接。TCP套接字通常不把IP地址捆绑到它的套接字上。当连接套接字时,内核将根据所用外出网络接口来选择源IP地址,而所用外出端口则取决于到达服务器所需的路径。如果TCP服务器没有把IP地址捆绑到它的套接字上,内核就会把发送的SYN的目的IP地址作为服务器的源IP地址(即服务器IP等于INADDR_ANY的情况)。
        实际上客户的源IP地址就是服务器的目的地址,服务器的源IP地址就是客户的目的地址,说到底也就只存在两个IP地址:客户IP跟服务器IP。
     
    3.connec函数
    t    TCP 客户用 connect 函数来与 TCP 服务器建立连接。
      
    #include <sys/socket.h>
     int connect( int sockfd, const struct sockaddr *servaddr, socklen_t addrlen );
     返回:若成功则为0,出错则为-1。

    参数说明:
        sockfd:            由 socket 函数返回的套接字描述符。    
        servaddr、addrlen:指向一个套接字地址结构的指针和该结构的大小。套接字地址结构必须含有服务器的IP地址和端口号。

    函数描述:
        客户在调用 connect 函数前并不一定得调用 bind 函数,如果需要的话,内核会确定源P地址,并选择一个临时端口作为源端口。所以在客户进程中的套接字一般只需指明客户所要连接的服务器的IP跟端口号。
        如果是 TCP 套接字,调用 connect 函数将激发 TCP 的三路握手。而且仅在连接成功或出错时才返回。其中出错的情况有如下几种:
        1-> TCP 客户没有收到 SYN 分节的响应。
        2-> TCP 服务器对客户的 SYN 分节的响应是 RST 。
        3-> 客户发出的 SYN 分节在某个路由器器上发生了错误。
        若 connect 调用失败则该套接字不再可用,必须关闭,我们不能对这样的套接字再次执行 connect 函数。

     

    4.listen 函数
    #include <sys/socket.h>
     int listen(int sockfd, int backlog);
             返回:若成功则为0,出错则为-1。

    函数描述:        
        listen 函数仅由 TCP 服务器调用,它做两件事情。
        (1)把一个未连接的套接字(主动)转换成一个被动套接字,指示内核应该接受指向该套接字的连接请求。
        (2)backlog 参数规定了内核应该为相应套接字排队的最大连接数。其中内核始终为监听套接字维护两个队列。
           (1)未完成连接队列,每个SYN分节对于其中一项:
               已由某个客户发出并到达服务器,而服务器正在等待待完成的TCP三路握手过程。这些套接字处于SYN_RCVD状态。
           (2)已完成连接队列
              每个已完成TCP三路握手过程的客户对应其中一项。这些套接字处于ESTABLISHED状态。
              backlog 就是这两个队列和的最大值。
        在三路握手完成之后,但在服务器调用 accept 之前到达的数据应由 TCP 服务器排队,最大数据量为相应已连接套接字的接收缓冲区的大小。

     

    5.accept 函数
        accept 函数由 TCP 服务器调用,用于从已完成连接队列头返回下一个已完成连接。如果已完成队列为空,那么进程被投入睡眠(假设套接字为默认的阻塞方式)。
    #include <sys/socket.h>
    int accept(int sockfd ,struct sockaddr *cliaddr, socklen_t *addrlen);
            返回:若成功则为非负已连接描述符和对端的IP和端口号,出错则为-1。

    参数说明:
        cliaddr、addrlen 用来返回已连接的对端进程(客户)的协议地址 。调用前,我们将由 *addrlen 所引用的整数值置为由cliaddr所指的套接字地址结构的长度,返回时,该整数值即为内核存放在该套接字地址机构内的确切字节数。

    函数描述:
        如果 accept 调用成功,那么其返回值是由内核自动生成的一个全新描述符,代表着与所返回客户的TCP连接。在讨论 accept 函数时,我们称它的第一个参数为监听套接字描述符(由 socket 创建,随后用作bind 和 listen 的第一个参数的描述符),称它的返回值为已连接套接字描述符。区分这两个套接字非常重要。一个服务器通常仅仅创建一个监听套接字,它在服务器的生命期内一直存在。内核为每个服务器进程接受的客户连接创建一个已连接套接字(也就是说对于它的TCP三路握手过程已经完成)。当服务器完成对某个连接客户的服务时,相应的已连接套接字就要被关闭。

     

    6.recv/recvfrom函数
        从套接字上接收一个消息。对于recvfrom ,可同时应用于面向连接的和无连接的套接字。recv一般只用在面向连接的套接字,几乎等同于recvfrom,只要将recvfrom的第五个参数设置NULL。如果消息太大,无法完整存放在所提供的缓冲区,根据不同的套接字,多余的字节会丢弃。假如套接字上没有消息可以读取,除了套接字已被设置为非阻塞模式,否则接收调用会等待消息的到来。

    #include <sys/types.h>
    #include <sys/socket.h>
    ssize_t recv(int sock, void *buf, size_t len, int flags);
    ssize_t recvfrom(int sock, void *buf, size_t len, int flags,  struct sockaddr *from, socklen_t *fromlen);

    参数:  
    sock:索引将要从其接收数据的套接字。
    buf:存放消息接收后的缓冲区。
    len:buf所指缓冲区的容量。
    flags:是以下一个或者多个标志的组合体,可通过or操作连在一起
    MSG_DONTWAIT:操作不会被阻塞。
    MSG_ERRQUEUE:指示应该从套接字的错误队列上接收错误值,依据不同的协议,错误值以某种辅佐性消息的方式传递进来,使用者应该提供足够大的缓冲区。导致错误的原封包通过msg_iovec作为一般的数据来传递。导致错误的数据报原目标地址作为msg_name被提供。错误以sock_extended_err结构形态被使用,定义如下
    #define SO_EE_ORIGIN_NONE    0
    #define SO_EE_ORIGIN_LOCAL   1
    #define SO_EE_ORIGIN_ICMP    2
    #define SO_EE_ORIGIN_ICMP6   3
    struct sock_extended_err
    {
        u_int32_t ee_errno;   /* error number */
        u_int8_t ee_origin; /* where the error originated */
        u_int8_t ee_type;    /* type */
        u_int8_t ee_code;    /* code */
        u_int8_t ee_pad;
        u_int32_t ee_info;    /* additional information */
        u_int32_t ee_data;    /* other data */
        /* More data may follow */
    };

    MSG_PEEK:指示数据接收后,在接收队列中保留原数据,不将其删除,随后的读操作还可以接收相同的数据。
    MSG_TRUNC:返回封包的实际长度,即使它比所提供的缓冲区更长, 只对packet套接字有效。
    MSG_WAITALL:要求阻塞操作,直到请求得到完整的满足。然而,如果捕捉到信号,错误或者连接断开发生,或者下次被接收的数据类型不同,仍会返回少于请求量的数据。
    MSG_EOR:指示记录的结束,返回的数据完成一个记录。
    MSG_TRUNC:指明数据报尾部数据已被丢弃,因为它比所提供的缓冲区需要更多的空间。
    MSG_CTRUNC:指明由于缓冲区空间不足,一些控制数据已被丢弃。
    MSG_OOB:指示接收到out-of-band数据(即需要优先处理的数据)。
    MSG_ERRQUEUE:指示除了来自套接字错误队列的错误外,没有接收到其它数据。
    from:指向存放对端地址的区域,如果为NULL,不储存对端地址。
    fromlen:作为入口参数,指向存放表示from最大容量的内存单元。作为出口参数,指向存放表示from实际长度的内存单元。

     

    7.send/sendto函数
         用于发送消息。send只可用于基于连接的套接字,send 和 write唯一的不同点是标志的存在,当标志为0时,send等同于write。sendto 和 sendmsg既可用于无连接的套接字,也可用于基于连接的套接字。除了套接字设置为非阻塞模式,调用将会阻塞直到数据被发送完。
     
    #include <sys/types.h>
    #include <sys/socket.h>
    ssize_t send(int sock, const void *buf, size_t len, int flags);
    ssize_t sendto(int sock, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);
    ssize_t sendmsg(int sock, const struct msghdr *msg, int flags);

    参数: 
    sock:索引将要从其发送数据的套接字。
    buf:指向将要发送数据的缓冲区。
    len:以上缓冲区的长度。len可以大于sizeof(buf),例如send("123",10)-->则实际发送10字节数据
    flags:是以下零个或者多个标志的组合体,可通过or操作连在一起
    MSG_DONTROUTE:不要使用网关来发送封包,只发送到直接联网的主机。这个标志主要用于诊断或者路由程序。
    MSG_DONTWAIT:操作不会被阻塞。
    MSG_EOR:终止一个记录。
    MSG_MORE:调用者有更多的数据需要发送。
    MSG_NOSIGNAL:当另一端终止连接时,请求在基于流的错误套接字上不要发送SIGPIPE信号。
    MSG_OOB:发送out-of-band数据(需要优先处理的数据),同时现行协议必须支持此种操作。
    to:指向存放接收端地址的区域,可以为NULL。
    tolen:以上内存区的长度,可以为0。
    msg:指向存放发送消息头的内存缓冲,结构形态如下
    struct msghdr {
        void           *msg_name;     
        socklen_t      msg_namelen;  
        struct iovec  *msg_iov;      
        size_t          msg_iovlen;   
        void           *msg_control;  
        socklen_t      msg_controllen;
        int             msg_flags;    
    };
    可能用到的数据结构有
    struct cmsghdr {
        socklen_t cmsg_len;   
        int       cmsg_level; 
        int       cmsg_type; 
    };

     

    8.getsockname 函数
      获取一个套接口的本地名字。
    #include <sys/socket.h>
        int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t *addrlen);
             返回:成功则不返回,出错则为-1。

    参数:
     sockfd:标识一个已捆绑套接口的描述字。   
       localaddr:接收套接口的地址(名字)。   
       addrlen:名字缓冲区长度。

    函数描述:
          getsockname()函数用于获取一个套接字的名字。它用于一个已捆绑或已连接套接字sockfd,本地地址将被返回。本调用特别适用于如下情况:未调用bind()就调用了connect(),这时唯有getsockname()调用可以获知系统内定的本地地址。在返回时,namelen参数包含了名字的实际字节数。   
         若一个套接字与INADDR_ANY捆绑,也就是说该套接字可以用任意主机的地址,此时除非调用connect()或accept()来连接,否则getsockname()将不会返回主机IP地址的任何信息。除非套接字被连接,WINDOWS套接字应用程序不应假设IP地址会从INADDR_ANY变成其他地址。这是因为对于多个主机环境下,除非套接字被连接,否则该套接字所用的IP地址是不可知的。

     

    9.getpeername 函数函数
      获取与套接口相连的端地址。
     int getpeername(int sockfd, struct sockaddr *peeraddr, socklen_t *addrlen);
             返回:成功则不返回,出错则为-1。

    函数描述:
     getpeername()函数用于从端口sockfd中获取与它捆绑的端口名,并把它存放在sockaddr类型的name结构中。它适用于数据报或流类套接口。

     

    10.setsockopt/getsockopt函数
     设置/获取套接口选项
      #include <winsock.h>
      int setsockopt(int sockfd, int level, int optname, void *optval,  int optlen);
      int getsockopt(int sockfd, int level, int optname, void *optval,  int *optlen) ;

    参数:
      s:标识一个套接口的描述字。
      level:选项定义的层次;目前仅支持SOL_SOCKET和IPPROTO_TCP层次。
      optname:需设置的选项。
      optval:指针,指向存放选项值的缓冲区。
      optlen:optval缓冲区的长度。

    注释:
            setsockopt()函数用于任意类型、任意状态套接口的设置选项值。尽管在不同协议层上存在选项,但本函数仅定义了最高的“套接口”层次上的选项。选项影响套接口的操作,诸如加急数据是否在普通数据流中接收,广播数据是否可以从套接口发送等等。

     

     

     

    展开全文
  • Linux C Socket UDP编程介绍及实例

    万次阅读 多人点赞 2016-11-25 15:48:55
    1、UDP网络编程主要流程 UDP协议的程序设计框架,客户端和服务器之间的差别在于服务器必须使用bind()函数来绑定侦听的本地UDP端口,而客户端则可以不进行绑定,直接发送到服务器地址的某个端口地址。框图如图1.3所示...
  • Linux 下的udp通信

    2016-12-04 12:16:15
    Linux 下的udp通信
  • linux下C++实现UDP通信

    千次阅读 2017-05-29 16:44:14
    简要介绍UDP原理,通过代码实例讲解。 本篇博客不强调server跟client 的概念,重在实现双方互通。 收的一方: socket()->bind()->recvfrom()->close() 发的一方:socket()->sendto()->close() 只有收数据的一方...
  • 本文主要介绍在Linux平台基于C++ socket实现UDP网络通信。 0初步构思 初步的构思是在Linux平台实现一个客户端和一个服务端,实现客户端发送消息,服务端接收消息。 1、通信流程 2、服务端代码 #include<...
  • linuxUDP通信例子

    千次阅读 2019-05-24 14:49:56
    UDP客户端在建立了插口后会直接用sendto函数发送数据,还隐含了一个操作, 那就是在发送数据之前,UDP会首先为该插口选择一个独立的UDP端口(在1024 -5000之间),将该插口置为已绑定状态。如果一个UDP客户端在建立...
  • 简单实现Linux与Windows之间的UDP通信 如图所示: 在Linux下使用Makefile进行编译,Makefile代码如下: CC = g++ SRCS = main.cpp udp.cpp OBJS = $(SRCS:.cpp=.o) EXEC = myapp start:$(OBJS) $(CC) -o $...
  • linuxudp通信例子

    万次阅读 2012-08-22 16:33:53
    UDP客户端在建立了插口后会直接用sendto函数发送数据,还隐含了一个操作, 那就是在发送数据之前,UDP会首先为该插口选择一个独立的UDP端口(在1024 -5000之间),将该插口置为已绑定状态。如果一个UDP客户端在...
  • Linux下C语言实现简单的udp通信

    千次阅读 2016-04-28 10:13:37
    用C语言实现UDP 通信。写一个udp 的客户端,可以向外发送消息。再写一个udp服务端,接收客户端的消息,并且打印出来。*事先说明: 在window和Linux中有一下结构: struct sockaddr { unsigned short; sa_...
  • linux系统下建立多线程程序设计,完成UDP网络通信的发送与接收,包括总结与源代码,实测效果可见链接https://blog.csdn.net/zxp121127/article/details/78506081
  • Linux和Windows间的UDP通信

    千次阅读 2018-07-01 08:55:13
    UDP(user datagram protocol)的中文叫用户数据报协议,属于传输层。...正因为UDP无需建立类如三次握手的连接,而使得通信效率很高。服务器端的步骤如下:1. socket: 建立一个socket2. bind:...
  • UDP通信

    千次阅读 2019-05-29 16:14:59
    UDP通信UDP简介UDP协议特性UDP协议与TCP协议的主要区别TCP协议简介TCP协议特性主要区别UDP协议应用场景UDP通信代码Linux系统下的UDP通信代码发送端接收端(阻塞模式)接收端(非阻塞模式)Windows系统下的UDP通信...
  • linux UDP 通信使用实例

    2014-08-27 17:01:06
    UDP Server程序 1、编写UDP Server程序的步骤 (1)使用socket()来建立一个UDP socket,第二个参数为SOCK_DGRAM。 (2)初始化sockaddr_in结构的变量,并赋值。sockaddr_in结构定义: struct sockaddr_in { uint8_t sin_...
  • QT实现UDP通信

    热门讨论 2020-07-30 23:32:45
    qt实现C/S的udp通信实例,保护客户端和服务器。
  • 网络通信UDPLinux/Windows)

    千次阅读 2016-04-04 10:38:40
    1、Window下UDP 首先,涉及到的API函数及相关的数据类型: (1)MAKEWORD()宏 用来将创建含有一个请求版本号的WORD值 (2)windows下的套接字库 WSAStartup() 加载套接字库 WSACleanup()  清除套接字库 上述两...
  • 前面的文章一系列文章有介绍了 linux 下常见的 IPC 机制,如管道、消息队列、信号量、共享内存。 之前有讲到共享内存是最高效的 IPC 方式,但是在 linux 环境下,应用最广泛的可能是 Socket。 什么是 Unix Domain ...
1 2 3 4 5 ... 20
收藏数 38,878
精华内容 15,551
热门标签
关键字:

udp通信linux代码