您好,登錄后才能下訂單哦!
本篇內容主要講解“C語言中socketpair的用法介紹”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“C語言中socketpair的用法介紹”吧!
socketpair()函數的聲明:
#include <sys/types.h> #include <sys/socket.h> int socketpair(int d, int type, int protocol, int sv[2]);
socketpair()函數用于創建一對無名的、相互連接的套接子。
如果函數成功,則返回0,創建好的套接字分別是sv[0]和sv[1];否則返回-1,錯誤碼保存于errno中。
基本用法:
這對套接字可以用于全雙工通信,每一個套接字既可以讀也可以寫。例如,可以往sv[0]中寫,從sv[1]中讀;或者從sv[1]中寫,從sv[0]中讀;
如果往一個套接字(如sv[0])中寫入后,再從該套接字讀時會阻塞,只能在另一個套接字中(sv[1])上讀成功;
讀、寫操作可以位于同一個進程,也可以分別位于不同的進程,如父子進程。如果是父子進程時,一般會功能分離,一個進程用來讀,一個用來寫。因為文件描述副sv[0]和sv[1]是進程共享的,所以讀的進程要關閉寫描述符, 反之,寫的進程關閉讀描述符。
舉例:
#include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <error.h> #include <errno.h> #include <sys/socket.h> #include <stdlib.h> const char* str = "SOCKET PAIR TEST."; int main(int argc, char* argv[]){ char buf[128] = {0}; int socket_pair[2]; pid_t pid; if(socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair) == -1 ) { printf("Error, socketpair create failed, errno(%d): %s\n", errno, strerror(errno)); return EXIT_FAILURE; } int size = write(socket_pair[0], str, strlen(str)); //可以讀取成功; read(socket_pair[1], buf, size); printf("Read result: %s\n",buf); return EXIT_SUCCESS; }
#include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <error.h> #include <errno.h> #include <sys/socket.h> #include <stdlib.h> const char* str = "SOCKET PAIR TEST."; int main(int argc, char* argv[]){ char buf[128] = {0}; int socket_pair[2]; pid_t pid; if(socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair) == -1 ) { printf("Error, socketpair create failed, errno(%d): %s\n", errno, strerror(errno)); return EXIT_FAILURE; } pid = fork(); if(pid < 0) { printf("Error, fork failed, errno(%d): %s\n", errno, strerror(errno)); return EXIT_FAILURE; } else if(pid > 0) { //關閉另外一個套接字 close(socket_pair[1]); int size = write(socket_pair[0], str, strlen(str)); printf("Write success, pid: %d\n", getpid()); } else if(pid == 0) { //關閉另外一個套接字 close(socket_pair[0]); read(socket_pair[1], buf, sizeof(buf)); printf("Read result: %s, pid: %d\n",buf, getpid()); } for(;;) { sleep(1); } return EXIT_SUCCESS; }
sendmsg, recvmsg , send三個函數的頭文件:
#include <sys/types.h> #include <sys/socket.h>
sendmsg函數
定義函數
int sendmsg(int s, const strcut msghdr *msg, unsigned int flags);
函數說明:sendmsg()用來將數據由指定的socket傳給對方主機.
參數s:為已建立好連線的socket, 如果利用UDP協議則不需經過連線操作.
參數msg:指向欲連線的數據結構內容, 參數flags 一般默認為0, 詳細描述請參考send().
返回值:成功返回發送的字節數,出錯返回-1
recvmsg函數
定義函數
int recvmsg(int s, struct msghdr *msg, unsigned int flags);
函數說明:recvmsg()用來接收遠程主機經指定的socket 傳來的數據.
參數s 為已建立好連線的socket, 如果利用UDP 協議則不需經過連線操作.
參數msg 指向欲連線的數據結構內容,
參數flags 一般設0, 詳細描述請參考send().
返回值:成功則返回接收到的字符數, 失敗則返回-1, 錯誤原因存于errno 中.
send函數
定義函數:int send(int s, const void * msg, int len, unsigned int falgs);
函數說明:send()用來將數據由指定的socket 傳給對方主機.
參數s 為已建立好連接的socket.
參數msg 指向欲連線的數據內容.
參數len 則為數據長度.
參數flags 一般設0, 其他數值定義如下:
MSG_OOB 傳送的數據以out-of-band 送出.
MSG_DONTROUTE 取消路由表查詢
MSG_DONTWAIT 設置為不可阻斷運作
MSG_NOSIGNAL 此動作不愿被SIGPIPE 信號中斷.
返回值:成功則返回實際傳送出去的字符數, 失敗返回-1. 錯誤原因存于errno.
結構msghdr定義如下:
struct msghdr { void *msg_name; //發送或接收數據的地址 socklen_t msg_namelen; //地址長度 strcut iovec * msg_iov; //要發送或接受數據 size_t msg_iovlen; //容器數據長度 void * msg_control; //附屬數據 size_t msg_controllen; //附屬數據長度 int msg_flags; //接收消息的標志 };
返回值:成功則返回實際傳送出去的字符數, 失敗返回-1, 錯誤原因存于errno
錯誤代碼:
1、EBADF 參數s 非合法的socket 處理代碼. 2、EFAULT 參數中有一指針指向無法存取的內存空間 3、ENOTSOCK 參數s 為一文件描述詞, 非socket. 4、EINTR 被信號所中斷. 5、EAGAIN 此操作會令進程阻斷, 但參數s 的socket 為不可阻斷. 6、ENOBUFS 系統的緩沖內存不足 7、ENOMEM 核心內存不足 EINVAL 傳給系統調用的參數不正確.
附屬數據msg_control結構
控制信息頭部本身由下面的C結構定義:
struct cmsghdr { socklen_t cmsg_len; int cmsg_level; int cmsg_type; /* u_char cmsg_data[]; */ };
其成員描述如下:
成員 描述 cmsg_len 附屬數據的字節計數,這包含結構頭的尺寸。這個值是由CMSG_LEN()宏計算的。 cmsg_level 這個值表明了原始的協議級別(例如,SOL_SOCKET)。 cmsg_type 這個值表明了控制信息類型(例如,SCM_RIGHTS)。 cmsg_data 這個成員并不實際存在,用來指明實際的額外附屬數據所在的位置。
用sendmsg來傳遞數據程序實例
/*sendmsg.c*/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> int main(int argc,char *argv[]) { int ret; /* 返回值 */ int sock[2]; /* 套接字對 */ struct msghdr msg; struct iovec iov[1]; char send_buf[100] = "it is a test"; struct msghdr msgr; struct iovec iovr[1]; char recv_buf[100]; /* 創建套接字對 */ ret = socketpair(AF_LOCAL,SOCK_STREAM,0,sock); if(ret == -1){ printf("socketpair err\n"); return 1; } /* sock[1]發送數據到本地主機 */ bzero(&msg, sizeof(msg)); msg.msg_name = NULL; /* void*類型 NULL本地地址*/ msg.msg_namelen = 0; iov[0].iov_base = send_buf; iov[0].iov_len = sizeof(send_buf); msg.msg_iov = iov;//要發送或接受數據設為iov msg.msg_iovlen = 1;//1個元素 printf("開始發送數據:\n"); printf("發送的數據為: %s\n", send_buf); ret = sendmsg(sock[1], &msg, 0 ); if(ret == -1 ){ printf("sendmsg err\n"); return -1; } printf("發送成功!\n"); /* 通過sock[0]接收發送過來的數據 */ bzero(&msg, sizeof(msg)); msgr.msg_name = NULL; msgr.msg_namelen = 0; iovr[0].iov_base = &recv_buf; iovr[0].iov_len = sizeof(recv_buf); msgr.msg_iov = iovr; msgr.msg_iovlen = 1; ret = recvmsg(sock[0], &msgr, 0); if(ret == -1 ){ printf("recvmsg err\n"); return -1; } printf("接收成功!\n"); printf("收到數據為: %s\n", recv_buf); /* 關閉sockets */ close(sock[0]); close(sock[1]); return 0; }
執行程序結果:
yu@ubuntu:~/Linux/217/pro_pool/socketpair$ gcc -o sendmsg sendmsg.c
yu@ubuntu:~/Linux/217/pro_pool/socketpair$ ./sendmsg
開始發送數據:
發送的數據為: it is a test
發送成功!
接收成功!接到數據為:it is a test
程序分析:由套接字sock[1]發數據到本地主機,由套接字sock[0]接收發送過來的數據。
到此,相信大家對“C語言中socketpair的用法介紹”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。