日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

UNP学习 高级I/O函数

發布時間:2023/12/18 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 UNP学习 高级I/O函数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

首先為一個I/O函數設置超時,這有三種方法。然后是三個read和write函數的變體:

  • recv和send,他們可以把含有標志的第四個參數從進程傳給內核;
  • readv和writev這兩個函數可以指定一個緩沖區的向量以輸入或輸出數據;
  • recvmsg和sendmsg在其他I/O函數的所有功能基礎上結合了新的接收和發送輔助數據的能力。

?

一、套接口超時

有三種方法給套接口上的I/O操作設置超時。

  • 調用alarm,在到達指定事件時產生SIGALRM信號。這涉及到信號處理,這一點隨不同實現而變化,而且可能與進程中其他已有的alarm調用沖突。
  • 使用select阻塞在等待I/O上,select內部有一個時間限制,以此代替在read或write調用上阻塞。
  • 使用新的SO_RCVTIMEO和SO_SNDTIMEO套接口選項。這種方法存在一個問題,即并不是所有的實現都能支持這兩個套接口選項。
  • ?

    二、recv和send函數

    #include <sys/socket.h>ssize_t recv(int sockfd, void *buff, size_t nbytes, int flags); ssize_t send(int sockfd, const void *buff, size_t nbytes, int flags); 返回:成功返回讀入或寫出的字節數,出錯返回-1
    前三個參數與read和write相同,flags的值或為0,或是一個或多個常值的邏輯或構成
    MSG_DONTROUTE:不查路由表
    MSG_DONTWAIT:本操作不阻塞
    MSG_OOB:發送或接收帶外數據
    MSG_PEEK:查看外來的消息
    MSG_WAITTALL:等待所有數據

    如果進程需要讓內核來更新標志,就必須用recvmsg代替recv或recvfrom。

    ?

    三、readv和writev函數

    #include <sys/uio.h>ssize_t readv(int filedes, const struct iovec *iov, int iovcnt); ssize_t writev(int filedes, const struct iovec *iov, int iovcnt); 返回:讀到或寫出的字節數,出錯時為-1 struct iovec {void *iov_base; /* starting address of buffer */size_t iov_len; /* size of buffer */ };

    readv和writev可用于任何描述字,不僅限于套接口描述字。

    ?

    四、recvmsg和sendmsg函數

    實際上,可以用recvmsg代替read、readv、readcv和recvfrom。

    #include <sys/socket.h>ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags); ssize_t sendmsg(int sockfd, struct msghdr *msg, int flags); 返回:成功時為讀入或寫出的字符數,出錯-1struct msghdr {void *msg_name; /* protocol address */用于未經連接的套接口socklen_t msg_namelen; /* size of protocol address */未經連接的套接口struct iovec *msg_iov; /* scatter/gather array */指明輸入或輸出的緩沖區數組size_t msg_iovlen; /* # elements in msg_iov */void *msg_control; /* ancillary data, must be aligned for a cmsghdr structure */socklen_t msg_controllen; /* length of ancillary data */指明可選輔助數據的位置和大小int msg_flags; /* flags returned by recvmsg() */標志變量 };

    ?輔助數據由一個或多個輔助數據對象組成,每個對象一個cmsghdr結構開頭,該結構在<sys/socket.h>中定義

    struct cmsghdr{socklen_t cmsg_len; /* length in bytes, including this structure */字節長度int cmsg_level; /* originating protocol */初始協議int cmsg_type; /* protocol-specific type */協議指定類型/* followed by unsigned char cmsg_data[] */真正的控制消息數據 };

    ?

    因為由recvmsg返回的輔助數據可以包括任意數目的輔助數據對象,為了對應用程序屏蔽可能出現的填充字節。

    在<sys/socket.h>中定義了以下五個宏,以簡化對輔助數據的處理。

    #include <sys/socket.h> #include <sys/param.h> /* for ALIGN macro on many implementations */ struct cmsghdr *CMSG_FIRSTHDR(struct msghdr *mhdrptr); 返回:指向第一個cmsghdr結構的指針,無輔助數據時為NULL struct cmsghdr *CMSG_NXTHDR(struct msghdr *mhdrptr, struct cmsghdr *cmsgptr); 返回:指向下一個cmsghdr結構的指針,不再有輔助數據對象時為NULL unsigned char *CMSG_DATA(struct cmsghdr *cmsgptr); 返回:指向與cmsghdr結構關聯的數據的第一個字節的指針 unsigned int CMSG_LEN(unsigned in length); 返回:給定數量下存儲在cmsg_len中的值 unsigned int CMSG_SPACE(unsigned int length); 返回:給定數據量下一個輔助數據對象的總大小

    一些使用例子:
    struct msghdr msg;
    struct cmsghdr *cmptr;

    cmptr = CMSG_FIRSTHDR(&msg);
    cmptr->cmsg_len = CMSG_LEN(sizeof(int));
    cmptr->cmsg_level = SOL_SOCKET;
    cmptr->cmsg_type = SCM_RIGHTS; /* send file description */
    *((int *)CMSG_DATA(cmptr)) = sendfd;

    ?使用msghdr的列子:

    1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 #include <errno.h> 5 #include <string.h> 6 #include <sys/types.h> 7 #include <sys/socket.h> 8 9 int main(int argc, char *argv[]) 10 { 11 int ret; 12 int sock[2]; 13 struct msghdr msg; 14 struct iovec iov[1]; 15 char send_buf[100] = "Hello"; 16 17 struct msghdr msgr; 18 struct iovec iovr[1]; 19 char recv_buf[100]; 20 21 ret = socketpair(AF_LOCAL, SOCK_STREAM, 0, sock); 22 if(ret == -1) { 23 printf("socketpair err\n"); 24 return 1; 25 } 26 27 /* sock[1] send data to local */ 28 bzero(&msg, sizeof(msg)); 29 msg.msg_name = NULL; 30 msg.msg_namelen = 0; 31 iov[0].iov_base = send_buf; 32 iov[0].iov_len = sizeof(send_buf); 33 msg.msg_iov = iov; 34 msg.msg_iovlen = 1; 35 36 printf("Starting send data: \n"); 37 printf("Send data: %s\n", send_buf); 38 ret = sendmsg(sock[1], &msg, 0); 39 if(ret == -1) { 40 printf("sendmsg err\n"); 41 return -1; 42 } 43 printf("Send successful\n"); 44 45 /* sock[0] recv data to local */ 46 bzero(&msgr, sizeof(msgr)); 47 msgr.msg_name = NULL; 48 msgr.msg_namelen = 0; 49 iovr[0].iov_base = recv_buf; 50 iovr[0].iov_len = sizeof(recv_buf); 51 msgr.msg_iov = iovr; 52 msgr.msg_iovlen = 1; 53 ret = recvmsg(sock[0], &msgr, 0); 54 if(ret == -1) { 55 printf("recvmsg err\n"); 56 return -1; 57 } 58 printf("Recv successful\n"); 59 printf("Recv data: %s\n", recv_buf); 60 61 close(sock[0]); 62 close(sock[1]); 63 64 return 0; 65 }

    運行結果:

    $ ./a.out
    Starting send data: Send data: Hello Send successful Recv successful Recv data: Hello

    ?

    轉載于:https://www.cnblogs.com/ch122633/p/8523244.html

    總結

    以上是生活随笔為你收集整理的UNP学习 高级I/O函数的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。