C語言 socketpair用法案例講解
socketpair()函數(shù)的聲明:
#include <sys/types.h> #include <sys/socket.h> int socketpair(int d, int type, int protocol, int sv[2]);
socketpair()函數(shù)用于創(chuàng)建一對無名的、相互連接的套接子。
如果函數(shù)成功,則返回0,創(chuàng)建好的套接字分別是sv[0]和sv[1];否則返回-1,錯(cuò)誤碼保存于errno中。
基本用法:
- 這對套接字可以用于全雙工通信,每一個(gè)套接字既可以讀也可以寫。例如,可以往sv[0]中寫,從sv[1]中讀;或者從sv[1]中寫,從sv[0]中讀;
- 如果往一個(gè)套接字(如sv[0])中寫入后,再從該套接字讀時(shí)會阻塞,只能在另一個(gè)套接字中(sv[1])上讀成功;
- 讀、寫操作可以位于同一個(gè)進(jìn)程,也可以分別位于不同的進(jìn)程,如父子進(jìn)程。如果是父子進(jìn)程時(shí),一般會功能分離,一個(gè)進(jìn)程用來讀,一個(gè)用來寫。因?yàn)槲募枋龈眘v[0]和sv[1]是進(jìn)程共享的,所以讀的進(jìn)程要關(guān)閉寫描述符, 反之,寫的進(jìn)程關(guān)閉讀描述符。
舉例:
一、讀寫操作位于同一進(jìn)程
#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;
}
二、讀寫操作位于不同進(jìn)程
#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) {
//關(guān)閉另外一個(gè)套接字
close(socket_pair[1]);
int size = write(socket_pair[0], str, strlen(str));
printf("Write success, pid: %d\n", getpid());
} else if(pid == 0) {
//關(guān)閉另外一個(gè)套接字
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函數(shù)的使用
sendmsg, recvmsg , send三個(gè)函數(shù)的頭文件:
#include <sys/types.h> #include <sys/socket.h>
sendmsg函數(shù)
定義函數(shù)
int sendmsg(int s, const strcut msghdr *msg, unsigned int flags);
函數(shù)說明:sendmsg()用來將數(shù)據(jù)由指定的socket傳給對方主機(jī).
參數(shù)s:為已建立好連線的socket, 如果利用UDP協(xié)議則不需經(jīng)過連線操作.
參數(shù)msg:指向欲連線的數(shù)據(jù)結(jié)構(gòu)內(nèi)容, 參數(shù)flags 一般默認(rèn)為0, 詳細(xì)描述請參考send().
返回值:成功返回發(fā)送的字節(jié)數(shù),出錯(cuò)返回-1
recvmsg函數(shù)
定義函數(shù)
int recvmsg(int s, struct msghdr *msg, unsigned int flags);
函數(shù)說明:recvmsg()用來接收遠(yuǎn)程主機(jī)經(jīng)指定的socket 傳來的數(shù)據(jù).
參數(shù)s 為已建立好連線的socket, 如果利用UDP 協(xié)議則不需經(jīng)過連線操作.
參數(shù)msg 指向欲連線的數(shù)據(jù)結(jié)構(gòu)內(nèi)容,
參數(shù)flags 一般設(shè)0, 詳細(xì)描述請參考send().
返回值:成功則返回接收到的字符數(shù), 失敗則返回-1, 錯(cuò)誤原因存于errno 中.
send函數(shù)
定義函數(shù):int send(int s, const void * msg, int len, unsigned int falgs);
函數(shù)說明:send()用來將數(shù)據(jù)由指定的socket 傳給對方主機(jī).
參數(shù)s 為已建立好連接的socket.
參數(shù)msg 指向欲連線的數(shù)據(jù)內(nèi)容.
參數(shù)len 則為數(shù)據(jù)長度.
參數(shù)flags 一般設(shè)0, 其他數(shù)值定義如下:
MSG_OOB 傳送的數(shù)據(jù)以out-of-band 送出.
MSG_DONTROUTE 取消路由表查詢
MSG_DONTWAIT 設(shè)置為不可阻斷運(yùn)作
MSG_NOSIGNAL 此動作不愿被SIGPIPE 信號中斷.
返回值:成功則返回實(shí)際傳送出去的字符數(shù), 失敗返回-1. 錯(cuò)誤原因存于errno.
結(jié)構(gòu)msghdr定義如下:
struct msghdr
{
void *msg_name; //發(fā)送或接收數(shù)據(jù)的地址
socklen_t msg_namelen; //地址長度
strcut iovec * msg_iov; //要發(fā)送或接受數(shù)據(jù)
size_t msg_iovlen; //容器數(shù)據(jù)長度
void * msg_control; //附屬數(shù)據(jù)
size_t msg_controllen; //附屬數(shù)據(jù)長度
int msg_flags; //接收消息的標(biāo)志
};
返回值:成功則返回實(shí)際傳送出去的字符數(shù), 失敗返回-1, 錯(cuò)誤原因存于errno
錯(cuò)誤代碼:
1、EBADF 參數(shù)s 非合法的socket 處理代碼. 2、EFAULT 參數(shù)中有一指針指向無法存取的內(nèi)存空間 3、ENOTSOCK 參數(shù)s 為一文件描述詞, 非socket. 4、EINTR 被信號所中斷. 5、EAGAIN 此操作會令進(jìn)程阻斷, 但參數(shù)s 的socket 為不可阻斷. 6、ENOBUFS 系統(tǒng)的緩沖內(nèi)存不足 7、ENOMEM 核心內(nèi)存不足 EINVAL 傳給系統(tǒng)調(diào)用的參數(shù)不正確.
附屬數(shù)據(jù)msg_control結(jié)構(gòu)
控制信息頭部本身由下面的C結(jié)構(gòu)定義:
struct cmsghdr {
socklen_t cmsg_len;
int cmsg_level;
int cmsg_type;
/* u_char cmsg_data[]; */
};
其成員描述如下:
成員 描述 cmsg_len 附屬數(shù)據(jù)的字節(jié)計(jì)數(shù),這包含結(jié)構(gòu)頭的尺寸。這個(gè)值是由CMSG_LEN()宏計(jì)算的。 cmsg_level 這個(gè)值表明了原始的協(xié)議級別(例如,SOL_SOCKET)。 cmsg_type 這個(gè)值表明了控制信息類型(例如,SCM_RIGHTS)。 cmsg_data 這個(gè)成員并不實(shí)際存在,用來指明實(shí)際的額外附屬數(shù)據(jù)所在的位置。
用sendmsg來傳遞數(shù)據(jù)程序?qū)嵗?/p>
/*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];
/* 創(chuàng)建套接字對 */
ret = socketpair(AF_LOCAL,SOCK_STREAM,0,sock);
if(ret == -1){
printf("socketpair err\n");
return 1;
}
/* sock[1]發(fā)送數(shù)據(jù)到本地主機(jī) */
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;//要發(fā)送或接受數(shù)據(jù)設(shè)為iov
msg.msg_iovlen = 1;//1個(gè)元素
printf("開始發(fā)送數(shù)據(jù):\n");
printf("發(fā)送的數(shù)據(jù)為: %s\n", send_buf);
ret = sendmsg(sock[1], &msg, 0 );
if(ret == -1 ){
printf("sendmsg err\n");
return -1;
}
printf("發(fā)送成功!\n");
/* 通過sock[0]接收發(fā)送過來的數(shù)據(jù) */
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("收到數(shù)據(jù)為: %s\n", recv_buf);
/* 關(guān)閉sockets */
close(sock[0]);
close(sock[1]);
return 0;
}
執(zhí)行程序結(jié)果:
yu@ubuntu:~/Linux/217/pro_pool/socketpair$ gcc -o sendmsg sendmsg.c
yu@ubuntu:~/Linux/217/pro_pool/socketpair$ ./sendmsg
開始發(fā)送數(shù)據(jù):
發(fā)送的數(shù)據(jù)為: it is a test
發(fā)送成功!
接收成功!接到數(shù)據(jù)為:it is a test
程序分析:由套接字sock[1]發(fā)數(shù)據(jù)到本地主機(jī),由套接字sock[0]接收發(fā)送過來的數(shù)據(jù)。
到此這篇關(guān)于C語言 socketpair用法案例講解的文章就介紹到這了,更多相關(guān)C語言 socketpair用法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++輸入一個(gè)字符串,把其中的字符按照逆序輸出的兩種方法解析
以下是對C++中輸入一個(gè)字符串,把其中的字符按照逆序輸出的兩種方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過來參考下2013-07-07
C++中for循環(huán)與while循環(huán)的區(qū)別總結(jié)
這篇文章主要給大家介紹了關(guān)于C++中for循環(huán)與while循環(huán)的區(qū)別的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
C++實(shí)現(xiàn)點(diǎn)云添加高斯噪聲功能
所謂高斯噪聲是指它的概率密度函數(shù)服從高斯分布(即正態(tài)分布)的一類噪聲,這篇文章主要給大家介紹了關(guān)于C++實(shí)現(xiàn)點(diǎn)云添加高斯噪聲功能的相關(guān)資料,需要的朋友可以參考下2021-07-07
C語言詳細(xì)分析結(jié)構(gòu)體的內(nèi)存對齊規(guī)則
C 數(shù)組允許定義可存儲相同類型數(shù)據(jù)項(xiàng)的變量,結(jié)構(gòu)是 C 編程中另一種用戶自定義的可用的數(shù)據(jù)類型,它允許你存儲不同類型的數(shù)據(jù)項(xiàng),本篇讓我們來了解C 的結(jié)構(gòu)體內(nèi)存對齊2022-07-07

