我正在编程UDP非阻塞套接字,并且具有功能
void recvflush(int sockfd) {
ssize_t num;
while (errno != EWOULDBLOCK) {
num = recvfrom(sockfd, NULL, maxpack, 0, NULL, NULL);
if (num < 0 && errno != EWOULDBLOCK)
error("recvfrom() failed", strerror(errno));
}
}
刷新接收缓冲区。但是,当我调用它时,它将返回EFAULT(错误地址),并且我确定在设置时已设置了sockfd。救命!
谢谢
答案 0 :(得分:2)
您是否出于某些原因期望,将NULL
指针指向recvfrom
会导致它刷新消息?您已经告诉它缓冲区的长度为maxpack
个字节,但是随后给了它一个无效的指针,所以EFAULT
是正确的和预期的errno
。
您应该能够提供为零的 length 来丢弃排队的消息:根据recvfrom(2)
手册页,如果提供的缓冲区长度对于消息来说太短,则剩余的数据字节将被丢弃;其中应包括丢弃所有所有个字节。
现在,一旦提供了零长度,就可以 提供一个NULL
指针,因为在这种情况下,不需要缓冲区的任何部分都有效。但这不是因为NULL
指针被特别识别,而是因为提供的长度不需要指向它的任何部分即可指向有效内存。
答案 1 :(得分:0)
根据function logInvoice() {
const wb = SpreadsheetApp.getActive(); // 'const' means we will not change what 'wb' means.
const sales = wb.getSheetByName("Sales Reports");
var lastSalesRow = sales.getLastRow(); // not 'const' since we will re-assign this primitive.
const invoice = wb.getSheetByName("Invoice");
const fullReport = invoice.getDataRange().getValues(); // Gets A1:___ into a 2D JS array
const data = [
fullReport[2][4], // E3
fullReport[1][4], // E2
/** I really don't know what you were doing with "=row() + 100000 - 2". If
* you were just trying to get a unique identifier, then use the next line: */
// Utilities.getUuid(),
fullReport[29][4], // E30
/**
* add more elements as needed
*/
];
// Write the summary data to the next row in the 'Sales Reports' sheet.
// Grabs the cell "A#" and then uses the size of the data to write to determine
// the size of the Range required.
sales.getRange(++lastSalesRow, 1, data.length, data[0].length).setValues(data);
// Reset the Invoice sheet to its blank slate.
invoice.getRangeList([
"C6", // R6C3
"B12:C28",
"E29"
]).clearContent();
}
的{{3}},在以下情况下报告recvfrom()
:
EFAULT
接收缓冲区指针指向进程的地址空间之外。
假设您的EFAULT
变量> 0,则maxpack
希望能够将字节写入recvfrom()
参数所指向的缓冲区,但是您正在传递{{1} }表示该参数,因此会出错。
为什么在致电 还要记住,UDP支持长度为0的数据包,在这种情况下, 尝试以下方法: 或者,如果 请注意,如果您的套接字不是非阻塞的,则不会报告buf
之前先检查NULL
?您应该先致电errno
,然后检查错误。并且在报告了任何错误 {em> recvfrom()
/ recvfrom()
,EWOULDBLOCK
或EAGAIN
以外的错误时停止循环。 / p>
EINTR
将返回0而不是-1,并且不会设置EMSGSIZE
。确保在循环中也考虑到这一点。recvfrom()
errno
不接受长度为0的缓冲区,则给它一个小的缓冲区以写入:void recvflush(int sockfd) {
ssize_t num;
do {
num = recvfrom(sockfd, NULL, 0, 0, NULL, NULL);
if (num < 0) {
if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
break;
if ((errno != EINTR) && (errno != EMSGSIZE)) {
error("recvfrom() failed", strerror(errno));
break;
}
}
}
while (true);
}
recvfrom()
/ void recvflush(int sockfd) {
ssize_t num;
char c;
do {
num = recvfrom(sockfd, &c, 1, 0, NULL, NULL);
if (num < 0) {
if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
break;
if ((errno != EINTR) && (errno != EMSGSIZE)) {
error("recvfrom() failed", strerror(errno));
break;
}
}
}
while (true);
}
,因为该调用将在数据可用之前阻塞,因此应使用EWOULDBLOCK
或EAGAIN
在进入select()
循环之前检查套接字是否有排队的数据包。