recv, recvfrom, recvmsg
recv,recvfrom,recvmsg函數(shù)用于從套接字接收信息。
ssize_t recv (int s, void *buf, size_t len, int flags);
ssize_t recvfrom (int s, void * restrict buf, size_t len, int flags,
struct sockaddr * restrict from, socklen_t * restrict fromlen);
ssize_t recvmsg (int s, struct msghdr *msg, int flags);
recvfrom和recvmsg系統(tǒng)調(diào)用用于從套接字接收消息,也可以用來接受套接字?jǐn)?shù)據(jù),不管其是否是面向連接的。 recv函數(shù)通常用于面向連接的套接字(參看[[[Open C 套接字: connect 方法|connect]]),等同于用空指針傳入from參數(shù)時(shí)
的recvfrom。所有三個(gè)例程都返回成功時(shí)的消息長(zhǎng)度。
recvmsg系統(tǒng)調(diào)用使用msghdr結(jié)構(gòu)將直接提供的參數(shù)個(gè)數(shù)減到最少,這個(gè)結(jié)構(gòu)具有以下格式,定義在sys/socket.h文件:
struct msghdr {
caddr_t msg_name; /* optional address */
u_int msg_namelen; /* size of address */
struct iovec *msg_iov; /* scatter/gather array */
u_int msg_iovlen; /* # elements in msg_iov */
caddr_t msg_control; /* ancillary data, see below */
u_int msg_controllen; /* ancillary data buffer len */
int msg_flags; /* flags on received message */
};
下面的代碼片段演示了recv, recvfrom, recvmsg函數(shù)的用法:
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
void Recv()
{
struct sockaddr_in serv_addr;
int sock_fd;
char line[10];
int size = 10;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
serv_addr.sin_port = htons(5000);
sock_fd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
connect(sock_fd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
recv(sock_fd, line, size, 0);
close(sock_fd);
}
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
void Sendto()
{
struct sockaddr_in sender_addr;
int sock_fd;
char line[15] = "Hello World!";
unsigned int size = sizeof(sender_addr);
sock_fd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
sender_addr.sin_family = AF_INET;
sender_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
sender_addr.sin_port = htons(5000);
recvfrom(sock_fd,line,13,0,(struct sockaddr*)&sender_addr,&size);
close(sock_fd);
}
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
void SendMsgRecvMsg()
{
int sock_fd;
unsigned int sender_len;
struct msghdr msg;
struct iovec iov;
struct sockaddr_in receiver_addr,sender_addr;
char line[10];
sock_fd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
receiver_addr.sin_family = AF_INET;
receiver_addr.sin_addr.s_addr = htonl(INADDR_ANY);
receiver_addr.sin_port = htons(5000);
bind(sock_fd,(struct sockaddr*)&receiver_addr,sizeof(receiver_addr));
sender_len = sizeof(sender_addr);
msg.msg_name = &sender_addr;
msg.msg_namelen = sender_len;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_iov->iov_base = line;
msg.msg_iov->iov_len = 10;
msg.msg_control = 0;
msg.msg_controllen = 0;
msg.msg_flags = 0;
recvmsg(sock_fd,&msg,0);
close(sock_fd);
}
這些調(diào)用返回接收的字節(jié)數(shù),或者如錯(cuò)誤發(fā)生返回-1。
==========================================================================================
【recv/recvfrom/recvmsg系統(tǒng)調(diào)用】
功能描述:
從套接字上接收一個(gè)消息。對(duì)于recvfrom 和 recvmsg,可同時(shí)應(yīng)用于面向連接的和無連接的套接字。recv一般只用在面向連接的套接字,幾乎等同于recvfrom,只要將recvfrom的第五個(gè)參數(shù)設(shè)置NULL。
如果消息太大,無法完整存放在所提供的緩沖區(qū),根據(jù)不同的套接字,多余的字節(jié)會(huì)丟棄。
假如套接字上沒有消息可以讀取,除了套接字已被設(shè)置為非阻塞模式,否則接收調(diào)用會(huì)等待消息的到來。
用法:
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int sock, void *buf, size_t len, int flags);
ssize_t recvfrom(int sock, void *buf, size_t len, int flags,
struct sockaddr *from, socklen_t *fromlen);
ssize_t recvmsg(int sock, struct msghdr *msg, int flags);
參數(shù):
sock:索引將要從其接收數(shù)據(jù)的套接字。
buf:存放消息接收后的緩沖區(qū)。
len:buf所指緩沖區(qū)的容量。
flags:是以下一個(gè)或者多個(gè)標(biāo)志的組合體,可通過or操作連在一起
MSG_DONTWAIT:操作不會(huì)被阻塞。
MSG_ERRQUEUE: 指示應(yīng)該從套接字的錯(cuò)誤隊(duì)列上接收錯(cuò)誤值,依據(jù)不同的協(xié)議,錯(cuò)誤值以某種輔佐性消息的方式傳遞進(jìn)來, 使用者應(yīng)該提供足夠大的緩沖區(qū)。導(dǎo)致錯(cuò)誤的原封包通過msg_iovec作為一般的數(shù)據(jù)來傳遞。導(dǎo)致錯(cuò)誤的數(shù)據(jù)報(bào)原目標(biāo)地址作為msg_name被提供。 錯(cuò)誤以sock_extended_err結(jié)構(gòu)形態(tài)被使用,定義如下
#define SO_EE_ORIGIN_NONE 0
#define SO_EE_ORIGIN_LOCAL 1
#define SO_EE_ORIGIN_ICMP 2
#define SO_EE_ORIGIN_ICMP6 3
struct sock_extended_err
{
u_int32_t ee_errno; /* error number */
u_int8_t ee_origin; /* where the error originated */
u_int8_t ee_type; /* type */
u_int8_t ee_code; /* code */
u_int8_t ee_pad;
u_int32_t ee_info; /* additional information */
u_int32_t ee_data; /* other data */
/* More data may follow */
};
MSG_PEEK:指示數(shù)據(jù)接收后,在接收隊(duì)列中保留原數(shù)據(jù),不將其刪除,隨后的讀操作還可以接收相同的數(shù)據(jù)。
MSG_TRUNC:返回封包的實(shí)際長(zhǎng)度,即使它比所提供的緩沖區(qū)更長(zhǎng), 只對(duì)packet套接字有效。
MSG_WAITALL:要求阻塞操作,直到請(qǐng)求得到完整的滿足。然而,如果捕捉到信號(hào),錯(cuò)誤或者連接斷開發(fā)生,或者下次被接收的數(shù)據(jù)類型不同,仍會(huì)返回少于請(qǐng)求量的數(shù)據(jù)。
MSG_EOR:指示記錄的結(jié)束,返回的數(shù)據(jù)完成一個(gè)記錄。
MSG_TRUNC:指明數(shù)據(jù)報(bào)尾部數(shù)據(jù)已被丟棄,因?yàn)樗人峁┑木彌_區(qū)需要更多的空間。
MSG_CTRUNC:指明由于緩沖區(qū)空間不足,一些控制數(shù)據(jù)已被丟棄。
MSG_OOB:指示接收到out-of-band數(shù)據(jù)(即需要優(yōu)先處理的數(shù)據(jù))。
MSG_ERRQUEUE:指示除了來自套接字錯(cuò)誤隊(duì)列的錯(cuò)誤外,沒有接收到其它數(shù)據(jù)。
from:指向存放對(duì)端地址的區(qū)域,如果為NULL,不儲(chǔ)存對(duì)端地址。
fromlen:作為入口參數(shù),指向存放表示from最大容量的內(nèi)存單元。作為出口參數(shù),指向存放表示from實(shí)際長(zhǎng)度的內(nèi)存單元。
msg:指向存放進(jìn)入消息頭的內(nèi)存緩沖,結(jié)構(gòu)形態(tài)如下
struct msghdr {
void *msg_name; /* optional address */
socklen_t msg_namelen; /* size of address */
struct iovec *msg_iov; /* scatter/gather array */
size_t msg_iovlen; /* # elements in msg_iov */
void *msg_control; /* ancillary data, see below */
socklen_t msg_controllen; /* ancillary data buffer len */
int msg_flags; /* flags on received message */
};
可能用到的數(shù)據(jù)結(jié)構(gòu)有
struct cmsghdr {
socklen_t cmsg_len; /* data byte count, including hdr */
int cmsg_level; /* originating protocol */
int cmsg_type; /* protocol-specific type */
/* followed by
u_char cmsg_data[]; */
};
返回說明:
成功執(zhí)行時(shí),返回接收到的字節(jié)數(shù)。另一端已關(guān)閉則返回0。失敗返回-1,errno被設(shè)為以下的某個(gè)值
EAGAIN:套接字已標(biāo)記為非阻塞,而接收操作被阻塞或者接收超時(shí)
EBADF:sock不是有效的描述詞
ECONNREFUSE:遠(yuǎn)程主機(jī)阻絕網(wǎng)絡(luò)連接
EFAULT:內(nèi)存空間訪問出錯(cuò)
EINTR:操作被信號(hào)中斷
EINVAL:參數(shù)無效
ENOMEM:內(nèi)存不足
ENOTCONN:與面向連接關(guān)聯(lián)的套接字尚未被連接上
ENOTSOCK:sock索引的不是套接字
轉(zhuǎn)載于:https://www.cnblogs.com/hnrainll/archive/2011/08/16/2141480.html
總結(jié)
以上是生活随笔為你收集整理的recv, recvfrom, recvmsg的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Netty中的策略者模式
- 下一篇: 魔戒1