- 浏览: 262293 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
ab0809:
写的很好,谢谢
c++中的 extern "C" -
eieihihi:
说得太好了,我就喜欢这种很透彻的说法
c++中的 extern "C" -
infollllll:
package com;import java.io.*;im ...
websocket通讯协议(10版本)简介 -
rocksent:
websocket draft10握手成功了,可是传数据一直失 ...
websocket通讯协议(10版本)简介 -
guanbeilang:
通过你的代码,学会了怎么从客户端接收消息,并改造成了nodej ...
websocket通讯协议(10版本)简介
c版本(UNIX高级编程中的例子):
// sendmsg.h #ifndef SENDMSG_H #define SENDMSG_H #include <sys/types.h> int send_fd(int fd, int fd_to_send); int recv_fd(int fd, ssize_t (*userfunc)(int, const void*, size_t)); #endif
// semdmsg.c #include "sendmsg.h" #include <sys/socket.h> #include <stdio.h> #include <stdlib.h> static struct cmsghdr* cmptr = NULL; static int CONTROLLEN = sizeof(struct cmsghdr) + sizeof(int); static int MAXLINE = 100; int send_fd(int fd, int fd_to_send) { struct iovec iov[1]; struct msghdr msg; char buf[2]; iov[0].iov_base = buf; iov[0].iov_len = 2; msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_name = NULL; msg.msg_namelen = 0; if (fd_to_send <= 0) { return -1; } if (cmptr == NULL && (cmptr = (struct cmsghdr*)malloc(CONTROLLEN)) == NULL) return -1; cmptr->cmsg_level = SOL_SOCKET; cmptr->cmsg_type = SCM_RIGHTS; cmptr->cmsg_len = CONTROLLEN; msg.msg_control = cmptr; msg.msg_controllen = CONTROLLEN; *(int*)CMSG_DATA(cmptr) = fd_to_send; buf[1] = 0; buf[0] = 0; if (sendmsg(fd, &msg, 0) != 2) return -1; return 0; } int recv_fd(int fd, ssize_t (*userfunc)(int, const void*, size_t)) { int newfd, nr, status; char *ptr; char buf[MAXLINE]; struct iovec iov[1]; struct msghdr msg; status = -1; for ( ; ; ) { iov[0].iov_base = buf; iov[0].iov_len = sizeof(buf); msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_name = NULL; msg.msg_namelen = 0; if (cmptr == NULL & (cmptr = (struct cmsghdr*)malloc(CONTROLLEN)) == NULL) { return -1; } msg.msg_control = cmptr; msg.msg_controllen = CONTROLLEN; if ((nr = recvmsg(fd, &msg, 0)) < 0) { // err_sys("recvmsg error"); } else if (nr == 0) { // err_ret("connection closed by server"); return -1; } for (ptr = buf; ptr < &buf[nr]; ) { if (*ptr++ == 0) { if (ptr != &buf[nr-1]) { // err_dump("message format error"); } status = *ptr & 0xFF; if (status == 0) { if (msg.msg_controllen != CONTROLLEN) { // err_dump("status = 0but no fd"); } newfd = *(int*)CMSG_DATA(cmptr); } else { newfd = -status; } nr -= 2; } } // if (nr > 0 && (&userfunc)(STDERR_FILENO, buf, nr) != nr) // { // return -1; // } if (status >= 0) return newfd; } }
c++版本,自己封装的:
//domainsocket.h /* * domainsocket.h * * Created on: Apr 13, 2012 * Author: song */ #ifndef DOMAINSOCKET_H_ #define DOMAINSOCKET_H_ #include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/un.h> #include <arpa/inet.h> #include <netinet/in.h> #include <unistd.h> #include <errno.h> #include <sys/stat.h> #include <fcntl.h> class DomainSocket { // the exact name of this class may be "DomainSocketListener" // but we call it "DomainSocket" temporary public: DomainSocket(); virtual ~DomainSocket(); int Bind(const char* path); int Listen(int n); int Accept(); int Connect(const char* path); // client call this to send data int Send(const void* buf, size_t len, int flags); // server call this to send data int Send(int sockfd, const void* buf, size_t len, int flags); // client receive int Recv(void *buf, size_t len, int flags); // server receive int Recv(int sockfd, void *buf, size_t len, int flags); /* * the four methods below used to send and receive file descriptor. * if you are server, you have one more argument than client whatever * send or receive. * */ // send file descriptor // domain socket client send fd need call this. int Sendfd(int fdToSend); // domain socket server send fd need call this. int Sendfd(int sockfd, int fdToSend); // received file descriptor as return value // return : // > 0 all right! // = 0 receive fail int Recvfd(); // received file descriptor as return value // ... ... ... ... int Recvfd(int sockfd); protected: void DelDSocketFilePath(); private: int m_fd; struct sockaddr_un m_addr; const char* m_path; struct cmsghdr* cmptr; int CONTROLLEN; int MAXLINE; int _Sendfd(int sockfd, int fdToSend); int _Recvfd(int sockfd); }; #endif /* DOMAINSOCKET_H_ */
//domainsocket.cpp #include "domainsocket.h" using namespace std; DomainSocket::DomainSocket() { m_fd = 0; m_path = NULL; cmptr = NULL; CONTROLLEN = sizeof(struct cmsghdr) + sizeof(int); MAXLINE = 100; ////////////////////////////////// int len; memset(&m_addr, 0, sizeof(m_addr)); if ((m_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { cout<<"create domain socket fail!"<<endl; // return -1; } cout<<"create domain socket ... , fd is '"<<m_fd<<"'"<<endl; } DomainSocket::~DomainSocket() { close(m_fd); DelDSocketFilePath(); } int DomainSocket::Bind(const char* path) { m_path = path; // if file exist delete it DelDSocketFilePath(); m_addr.sun_family = AF_UNIX; strcpy(m_addr.sun_path, (char*)m_path); // bind if (bind(m_fd, (struct sockaddr*)&m_addr, sizeof(m_addr)) < 0) { cout<<"domain bind fail!, errno is '"<<errno<<"' [reason:" <<strerror(errno)<<"]"<<endl; close(m_fd); DelDSocketFilePath(); return -1; } cout<<"domain bind (socket and sockaddr) ..."<<endl; return 0; } int DomainSocket::Listen(int n) { if (listen(m_fd, n) < 0) { cout<<"domain listen fail!, errno is '"<<errno<<"' [reason:" <<strerror(errno)<<"]"<<endl; close(m_fd); DelDSocketFilePath(); return -1; } cout<<"domain listen ..."<<endl; return 0; } int DomainSocket::Accept() { struct sockaddr cli_addr; int new_fd; int len = sizeof(cli_addr); if ((new_fd = accept(m_fd, (struct sockaddr*)&cli_addr, (socklen_t*)&len)) < 0) { cout<<"domain accept fail!, errno is '"<<errno<<"' [reason:"<<strerror(errno)<<"]"<<endl; close(m_fd); DelDSocketFilePath(); return -1; } cout<<" domain accept a new fd '"<<new_fd<<"'"<<endl; return new_fd; } int DomainSocket::Connect(const char* path) { sockaddr_un server_addr; server_addr.sun_family = AF_UNIX; strcpy(server_addr.sun_path, path); if (connect(m_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) { cout<<"connect fail, err msg: "<<strerror(errno)<<endl; close(m_fd); return -1; } } int DomainSocket::Send(const void *buf, size_t len, int flags) { return send(m_fd, buf, len, flags); } int DomainSocket::Send(int sockfd, const void *buf, size_t len, int flags) { return send(sockfd, buf, len, flags); } int DomainSocket::Recv(void *buf, size_t len, int flags) { return recv(m_fd, buf, len, flags); } int DomainSocket::Recv(int sockfd, void *buf, size_t len, int flags) { return recv(sockfd, buf, len, flags); } int DomainSocket::Sendfd(int fdToSend) { return _Sendfd(m_fd, fdToSend); } int DomainSocket::Sendfd(int sockfd, int fdToSend) { return _Sendfd(sockfd, fdToSend); } int DomainSocket::Recvfd() { return _Recvfd(m_fd); } int DomainSocket::Recvfd(int sockfd) { return _Recvfd(sockfd); } int DomainSocket::_Sendfd(int sockfd, int fdToSend) { struct iovec iov[1]; struct msghdr msg; char buf[2]; iov[0].iov_base = buf; iov[0].iov_len = 2; msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_name = NULL; msg.msg_namelen = 0; if (fdToSend <= 0) { return -1; } if (cmptr == NULL && (cmptr = (struct cmsghdr*)malloc(CONTROLLEN)) == NULL) return -1; cmptr->cmsg_level = SOL_SOCKET; cmptr->cmsg_type = SCM_RIGHTS; cmptr->cmsg_len = CONTROLLEN; msg.msg_control = cmptr; msg.msg_controllen = CONTROLLEN; *(int*)CMSG_DATA(cmptr) = fdToSend; buf[1] = 0; buf[0] = 0; if (sendmsg(sockfd, &msg, 0) != 2) return -1; return 0; } int DomainSocket::_Recvfd(int sockfd) { int newfd, nr, status; char *ptr; char buf[MAXLINE]; struct iovec iov[1]; struct msghdr msg; status = -1; for ( ; ; ) { iov[0].iov_base = buf; iov[0].iov_len = sizeof(buf); msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_name = NULL; msg.msg_namelen = 0; if (cmptr == NULL & (cmptr = (struct cmsghdr*)malloc(CONTROLLEN)) == NULL) { return -1; } msg.msg_control = cmptr; msg.msg_controllen = CONTROLLEN; if ((nr = recvmsg(sockfd, &msg, 0)) < 0) { // err_sys("recvmsg error"); } else if (nr == 0) { // err_ret("connection closed by server"); return -1; } for (ptr = buf; ptr < &buf[nr]; ) { if (*ptr++ == 0) { if (ptr != &buf[nr-1]) { // err_dump("message format error"); } status = *ptr & 0xFF; if (status == 0) { if (msg.msg_controllen != CONTROLLEN) { // err_dump("status = 0but no fd"); } newfd = *(int*)CMSG_DATA(cmptr); } else { newfd = -status; } nr -= 2; } } // if (nr > 0 && (&userfunc)(STDERR_FILENO, buf, nr) != nr) // { // return -1; // } if (status >= 0) return newfd; } } void DomainSocket::DelDSocketFilePath() { if (!m_path) return; unlink(m_path); }
发表评论
-
c++ vector list map在遍历中删除元素
2013-05-07 14:47 5062c++ STL 中的vector, list, map ... -
c++ 构造函数和析构函数调用顺序
2013-04-25 16:54 1200#include <iostream> ... -
epoll高效的原因
2013-03-18 11:10 1054epoll高效的原因: 使用内核中断实现,中断后调用 ... -
unix domain socket传递描述符
2012-04-25 15:18 978用unix domain socket在进程间传递描述符。 ... -
C++中的虚函数和虚函数表
2012-04-02 18:17 970请看这一篇文章: http://hi.baidu.com/w ... -
c++中函数参数返回值用string好还是const char *好
2012-02-01 07:38 9828有这样一个函数test需要两个字符串作为参数,那么test的原 ... -
google的gtest测试框架
2011-12-21 18:17 864http://www.cnblogs.com/coderzh/ ... -
windows下TCP通讯
2011-12-20 18:17 1067客户端 #include <iostream> ... -
静态库与共享库
2011-11-01 19:00 1715在用c c++编程时经常用到库,库有静态的,和共享 ... -
c++线程池
2011-09-26 09:17 838 -
websocket通讯协议(10版本)简介
2011-09-22 18:27 15109前言: 工作中用到 ... -
epoll服务器
2011-09-21 22:33 813epoll服务器。 ... -
c,c++ little knowledge
2011-08-31 15:00 6781. 把一个string型字符串全部转成小写。 ... -
c++中的拷贝构造函数
2011-07-14 16:44 1135int a = 2; int b = a; ... -
简单的tcp通讯
2011-07-12 14:55 891简单的tcp通讯例子。 server端 /* ... -
c++中的 extern "C"
2011-06-21 20:33 23808比如说你用C 开发 ... -
c语言操作mysql数据库(Ubuntu11.04)
2011-06-11 17:43 2934系统:Ubuntu11.04 1.刚安装 ... -
全局宏定义
2010-12-22 22:59 5490首先我们要理解定义和声明的区别,举个常见的例子,比 ...
相关推荐
“工具”可能是指一些利用Unix域套接字和描述符传递的实用工具或库,例如libsocketcan用于CAN总线通信,或者某些进程间通信框架如ZeroMQ,它们可能在内部使用了Unix域套接字来高效地传递文件描述符。 总的来说,...
2. **文件描述符传递**:当一个进程通过 `recvmsg()` 接收到另一个进程发送过来的文件描述符后,它必须负责关闭这个文件描述符,否则会导致资源泄露。 3. **权限验证**:Unix Domain Socket 通过文件系统的权限...
每次成功接受连接后都会返回一个新的Socket文件描述符,用于后续的数据交换。 5. **发送和接收数据**:一旦连接建立,就可以使用`send()`和`recv()`函数来发送和接收数据。 6. **断开连接**:使用`close()`函数...
Unix域Socket分为两种类型:文件描述符类型(SOCK_STREAM)和数据报类型(SOCK_DGRAM)。文件描述符类型类似于TCP Socket,提供面向连接、可靠的字节流服务;而数据报类型则类似UDP Socket,是无连接的,数据报会被...
在进程间通信(IPC)中,能够直接传输文件描述符是非常实用的功能。这种能力使得服务器进程能够执行所有与文件相关的操作,如网络名称解析、调制解调器拨号、文件锁定协商等,并最终向请求方返回一个可用于后续I/O操作...
Socket也具有一个类似于打开文件的函数调用Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。常用的Socket类型有两种:流式Socket(SOCK_STREAM)和数据报式...
在Linux IPC中,socket通信主要分为两种类型:基于文件描述符的Unix Domain Socket(UDS)和基于网络协议的Inet Domain Socket。 **一、Unix Domain Socket** Unix Domain Socket,也称为本地域socket或文件域...
3. 在描述符传递期间,内核会将其标记为"在飞行中",即使发送方尝试关闭,内核也会保持其在接收进程中的打开状态,增加引用计数。 4. 描述符通过`msg_control`字段发送,通常伴随着至少1字节的数据,以区分“无数据...
2. 文件描述符:UNIX Socket是基于文件系统的,每个套接字都有一个唯一的文件描述符,用于读写操作。 3. 地址:UNIX Socket的地址是路径名,位于文件系统中。连接时,客户端查找这个路径来找到服务器端的套接字。 ...
总的来说,Linux下的进程间描述符传递利用了Unix域套接字和内核的特殊处理,通过`sendmsg`和`recvmsg`函数实现了描述符的安全转移。这种方法允许进程间共享文件描述符,极大地扩展了进程通信的能力,尤其是在需要...
2. **创建Socket**: 使用`socket()`函数创建一个Socket描述符,指定协议类型(如TCP或UDP)和地址族(如AF_INET用于IPv4)。 3. **绑定地址**: 使用`bind()`函数将Socket与特定的IP地址和端口号关联,以便其他设备...
它提供了一个简单的页面来建立 Unix domain socket 来接收来自 libafdt 服务器中的文件描述请求或者是传输文件描述信息到客户端。通过底层和同步接口传输数据报的时候需要使用 libevent。libafdt 有两个高层接口:...
Unix域套接字提供了类似文件系统的接口,使得进程可以通过文件描述符进行通信。它们有两种主要类型:流式(SOCK_STREAM)和数据报(SOCK_DGRAM),分别对应于TCP和UDP的特性。流式Unix域套接字提供可靠的、面向连接...
sockfd是Socket描述符,buf是接收数据缓冲区指针,len是最大接收数据长度,flags表示额外选项。 - **`close(sockfd)`**:关闭Socket。sockfd是Socket描述符。 #### 七、非阻塞选项 在某些情况下,可能需要Socket在...
- **资源管理**:Unix域套接字可以实现文件描述符的传递,这在网络套接字中是不可行的。 Unix域套接字的使用场景包括: - 进程间通信:如守护进程与用户界面的通信。 - 服务替换:在开发和测试环境中,可以用Unix域...
- **Socket创建**: 通过系统调用`socket()`来创建一个Socket,并返回一个Socket描述符。之后可以通过该描述符进行`send()`和`recv()`操作来发送和接收数据。 - **Socket调用**: 虽然可以使用`read()`和`write()`函数...
程序员可以通过socket()函数创建Socket,并获取一个整型的Socket描述符,后续的所有操作都将通过该描述符进行。Socket类型主要有两种,分别是流式Socket(SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。流式Socket...
其中,`sockfd`是`socket()`函数返回的Socket描述符,`my_addr`是一个指向包含本地地址信息的`sockaddr`结构的指针,`addrlen`则是结构的大小。 `sockaddr`是一个通用的地址结构,通常我们会使用更具体的结构,如`...
Socket编程的核心是创建、配置和使用Socket描述符。 1. **Socket的创建** 创建Socket的过程始于`socket()`函数调用。这个函数的参数包括协议族(domain)、Socket类型(type)和协议(protocol)。通常,对于TCP/...