本文主要介绍C语言中socketpair用法的案例讲解。本文通过一个简单的案例来说明对这项技术的理解和使用。以下是详细内容,有需要的朋友可以参考一下。
socket()函数的声明:
#包含sys/types.h
#包含sys/socket.h
int socketpair(int d,int type,int protocol,int SV[2]);
socket()函数用于创建一对相互连接的无名套接字。
如果函数成功,则返回0,创建的套接字分别为sv[0]和SV[1];否则,返回-1,错误代码保存在errno中。
基本用法:
这一对套接字可以用于全双工通信,每个套接字都可以被读取或写入。比如你可以写sv[0],读SV[1];或者从sv[1]写,从sv[0]读;
如果你写一个套接字(比如sv[0])然后从那个套接字读会阻塞,你只能在另一个套接字(sv[1])读成功;
读写操作可以在同一个进程中,也可以在不同的进程中,比如父子进程。如果是父子进程,通常功能是分开的,一个进程读,一个进程写。因为文件描述对sv[0]和sv[1]是由进程共享的,所以读进程应该关闭写描述符,否则,写进程应该关闭读描述符。
示例:
一、读写操作位于同一进程
#包含stdio.h
#包含字符串. h
#包括unistd.h
#包含sys/types.h
#包含错误. h
#包含错误号h
#包含sys/socket.h
#包含stdlib.h
const char* str='套接字对测试';
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失败,errno(%d): %s\n ',errno,strerror(errno));
返回EXIT _ FAILURE
}
int size=write(socket_pair[0],str,strlen(str));
//可以成功阅读;
read(socket_pair[1],buf,size);
printf('读取结果:%s\n ',buf);
返回EXIT _ SUCCESS
}
二、读写操作位于不同进程
#包含stdio.h
#包含字符串. h
#包括unistd.h
#包含sys/types.h
#包含错误. h
#包含错误号h
#包含sys/socket.h
#包含stdlib.h
const char* str='套接字对测试';
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失败,errno(%d): %s\n ',errno,strerror(errno));
返回EXIT _ FAILURE
}
PID=fork();
如果(pid 0) {
printf('Error,fork failed,errno(%d): %s\n ',errno,strerror(errno));
返回EXIT _ FAILURE
} else if(pid 0) {
//关闭另一个套接字
close(socket _ pair[1]);
int size=write(socket_pair[0],str,strlen(str));
printf('写入成功,pid: %d\n ',getpid());
} else if(pid==0) {
//关闭另一个套接字
close(socket _ pair[0]);
read(socket_pair[1],buf,sizeof(buf));
printf('读取结果:%s,pid: %d\n ',buf,getpid());
}
for(;) {
睡眠(1);
}
返回EXIT _ SUCCESS
}
sendmsg, recvmsg , send函数的使用
三个函数的头文件:sendmsg,recvmsg,send:
#包含sys/types.h
#包含sys/socket.h
Sendmsg函数
定义函数
int sendmsg(int s,const strcut msghdr *msg,unsigned int flags);
函数描述:sendmsg()用于将数据从指定的套接字传输到另一个主机。
参数s:已建立连接的套接字。如果使用UDP协议,则没有连接操作。
参数msg:指要连接的数据结构内容,参数flags一般默认为0。详细描述请参考send()。
返回值:成功返回发送的字节数,错误返回-1。
Recvmsg函数
定义函数
int recvmsg(int s,struct msghdr *msg,unsigned int flags);
函数:recvmsg()用于通过指定的套接字从远程主机接收数据。
参数s是已建立连接的套接字。如果使用UDP协议,则不需要连接操作。
msg参数指向要连接的数据结构内容,
参数flags一般设置为0,详细描述请参考send()。
返回值:如果成功,则返回接收的字符数,如果失败,则返回-1。错误原因存储在errno中。
发送功能
定义:int send (int s,constvoid * msg,int len,unsigned int falgs);
函数描述:send()用于将数据从指定的套接字发送到另一台主机。
参数s是已建立连接的套接字。
msg参数指向要连接的数据内容。
参数len是数据长度。
参数flags一般设置为0,其他值定义如下:
MSG_OOB发送的数据是带外发送的
MSG_DONTROUTE取消路由表查询
MSG_DONTWAIT设置为非阻塞操作。
MSG_NOSIGNAL这个动作不愿意被SIGPIPE信号中断。
返回值:如果成功,返回实际传输的字符数;如果失败,将返回-1。错误原因存储在errno中。
结构msghdr定义如下:
结构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是一个非法的套接字处理代码。
2.默认参数中的指针指向不可访问的内存空间。
3.ENOTSOCK参数s是一个文件描述符,而不是一个套接字。
4.EINTR被信号中断。
5.伊根。这个操作会阻塞进程,但是参数s的套接字是不可阻挡的。
6.ENOBUFS系统的缓冲内存不足。
7.ENOMEM的核心内存不足,EINVAL传递给系统调用的参数不正确。
辅助数据消息_控制结构
控制头本身由以下C结构定义:
结构cmsghdr {
socklen _ t cmsg _ len
int cmsg _ level
int cmsg _ type
/* u _ char cmsg _ data[];*/
};
其成员描述如下:
成员描述
cmsg_len附属数据的字节数,包含结构头的大小。这个值是由CMSG _伦()宏计算的。
值cmsg_level表示原始协议级别(例如,SOL_SOCKET)。
cmsg_type的值指示控制信息的类型(例如,SCM_RIGHTS)。
成员cmsg_data实际上并不存在,它用于指示实际附加附属数据的位置。
使用sendmsg传输数据程序实例
/*sendmsg.c*/
#包含stdio.h
#包含stdlib.h
#包括unistd.h
#包含错误号h
#包含字符串. h
#包含sys/types.h
#包含sys/socket.h
int main(int argc,char *argv[])
{
int ret/*返回值*/
int sock[2];/*插座对*/
struct msghdr msg
struct io vec iov[1];
char send_buf[100]='这是一个测试';
结构msghdr msgr
struct io vec iovr[1];
char recv _ buf[100];
/*创建套接字对*/
ret=socketpair(AF_LOCAL,SOCK_STREAM,0,SOCK);
if(ret==-1){
printf(' socket pair err \ n ');
返回1;
}
/* sock[1]向本地主机发送数据*/
bzero(msg,sizeof(msg));
msg.msg _ name=NULL/* void* type NULL本地地址*/
msg . msg _ name len=0;
iov[0]。iov _ base=send _ buf
iov[0]。iov _ len=sizeof(send _ buf);
msg.msg _ iov=iov//要发送或接收的数据设置为iov
msg . msg _ iov len=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 _ name len=0;
iovr[0]。iov _ base=recv _ buf
iovr[0]。iov _ len=sizeof(recv _ buf);
msgr.msg _ iov=iovr
msgr . msg _ iov len=1;
ret=recvmsg(sock[0],msgr,0);
if(ret==-1 ){
printf(' recvmsg err \ n ');
return-1;
}
Printf('接收成功!\ n’);
Printf('接收的数据:%s\n ',recv _ buf);
/*关闭套接字*/
close(sock[0]);
close(sock[1]);
返回0;
}
执行结果:
Yu @ Ubuntu:~/Linux/217/pro _ pool/socket pair $ gcc-o sendmsg sendmsg . c
Yu @ Ubuntu:~/Linux/217/pro _ pool/socket pair $。/sendmsg
开始发送数据:
发送的数据是:这是一个测试。
发送成功!
已成功接收!
收到的数据是:是测试。
程序分析:Socket sock[1]向本地主机发送数据,Socket sock[0]接收发送的数据。
本文关于C语言socketpair使用案例的讲解到此为止。关于C语言socketpair用法的更多信息,请搜索我们之前的文章或者继续浏览下面的相关文章。希望大家以后能多多支持我们!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。