我在Linux上的一个项目使用了阻塞套接字.事情发生非常连续,所以非阻塞只会让事情变得更复杂.无论如何,我发现经常一个recv()
调用返回-1
与errno
设置为EAGAIN
.
该man
页面只是真正提到非阻塞套接字发生这种情况,这是有道理的.如果没有阻塞,则套接字可能可用,也可能不可用,因此您可能需要重试.
什么会导致阻塞套接字发生?我可以做些什么来避免它吗?
目前,我处理它的代码看起来像这样(我在错误时抛出异常,但除此之外它是一个非常简单的包装器recv()
):
int ret;
do {
ret = ::recv(socket, buf, len, flags | MSG_NOSIGNAL);
} while(ret == -1 && errno == EAGAIN);
if(ret == -1) {
throw socket_error(strerror(errno));
}
return ret;
Run Code Online (Sandbox Code Playgroud)
这甚至是正确的吗?这种EAGAIN
情况经常受到打击.
编辑:我注意到的一些可能相关的事情.
我在套接字上设置了读取超时setsockopts()
,但设置为30秒.这种EAGAIN
情况经常发生在每30秒一次.修正我的调试有缺陷,EAGAIN
不会像我想象的那样经常发生.也许是超时触发.
为了连接,我希望能够连接超时,所以我暂时将套接字设置为非阻塞.该代码如下所示:
int error = 0;
fd_set rset;
fd_set wset;
int n;
const SOCKET sock = m_Socket;
// set the socket …
Run Code Online (Sandbox Code Playgroud)因此,FILE流可以同时具有输入和输出缓冲区.您可以使用调整输出流setvbuf
(我不知道任何使用输入缓冲区大小和行为的方法).
此外,默认情况下缓冲区是BUFSIZ
(不确定这是POSIX还是C的东西).这对于stdin
/ stdout
/ 这意味着什么stderr
,但新打开的文件的默认值是什么?它们是否针对输入和输出进行缓冲?或者也许只有一个?
如果它是缓冲的,输出默认为阻塞或行模式吗?
编辑:我已经做了一些测试,看看Jonathan Leffler的回答如何影响现实世界的节目.看来如果你做了一个读,那么写.写入将导致输入缓冲区的未使用部分完全丢弃.事实上,将会有一些寻求将事物保持在正确的文件偏移量.我用这个简单的测试程序:
/* input file contains "ABCDEFGHIJKLMNOPQRSTUVWXYZ" */
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *f = fopen("test.txt", "r+b");
char ch;
fread(&ch, 1, 1, f);
fwrite("test", 4, 1, f);
fclose(f);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
导致以下系统调用:
read(3, "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n", 4096) = 27 // attempt to read 4096 chars, got 27
lseek(3, -26, SEEK_CUR) = 1 // at this point, I've done my write already, so forget the …
Run Code Online (Sandbox Code Playgroud) 我有一个Qt小部件,它只接受十六进制字符串作为输入.将输入字符限制为非常简单[0-9A-Fa-f]
,但我想让它显示"bytes"之间的分隔符,例如,如果分隔符是空格,而用户类型0011223344
我希望行编辑显示00 11 22 33 44
现在如果用户按下退格键3次,然后我想要它显示00 11 22 3
.
我几乎拥有我想要的东西,到目前为止只有一个微妙的错误,涉及使用删除键删除分隔符.有没有人有更好的方法来实现这个验证器?到目前为止,这是我的代码:
class HexStringValidator : public QValidator {
public:
HexStringValidator(QObject * parent) : QValidator(parent) {}
public:
virtual void fixup(QString &input) const {
QString temp;
int index = 0;
// every 2 digits insert a space if they didn't explicitly type one
Q_FOREACH(QChar ch, input) {
if(std::isxdigit(ch.toAscii())) {
if(index != 0 && (index & 1) == 0) {
temp += ' ';
}
temp …
Run Code Online (Sandbox Code Playgroud) 我只是想着实施std::string::substr
.它返回一个新std::string
对象,这对我来说似乎有点浪费.为什么不返回一个引用原始字符串内容的对象,并且可以隐式赋值给std::string
?一种对实际复制的懒惰评价.这样的类看起来像这样:
template <class Ch, class Tr, class A>
class string_ref {
public:
// not important yet, but *looks* like basic_string's for the most part
private:
const basic_string<Ch, Tr, A> &s_;
const size_type pos_;
const size_type len_;
};
Run Code Online (Sandbox Code Playgroud)
这个类的公共接口将模仿真实的所有只读操作std::string
,因此使用将是无缝的.std::string
然后可以有一个新的构造函数,string_ref
因此用户永远不会更聪明.在您尝试"存储"结果的那一刻,您最终会创建一个副本,因此引用没有真正的问题指向数据,然后在其背后进行修改.
想法是这样的代码:
std::string s1 = "hello world";
std::string s2 = "world";
if(s1.substr(6) == s2) {
std::cout << "match!" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
std::string
总共不会构造2个对象.对于执行大量字符串操作的代码来说,这似乎是一种有用的优化.当然,这不仅适用于std::string
任何可以返回其内容子集的类型.
据我所知,没有实现这样做.
我想问题的核心是:
给定一个可以根据需要隐式转换为类的类std::string
,是否符合库编写者的标准,将成员的原型更改为返回类型?或者更一般地说,库编写者是否有余地在这些类型的情况下作为优化返回"代理对象"而不是常规对象?
我的直觉是,这是不允许的,原型必须完全匹配.鉴于您不能单独重载返回类型,这将使图书馆编写者无法利用这些类型的情况.就像我说的,我认为答案是否定的,但我想我会问:-).
我是Qt的新手,我正在创建一个简单的应用程序,它将播放音频文件.我意识到在写作时我缺少用于音频的Qt Multimedia API:
#include <QAudioOutput>
Run Code Online (Sandbox Code Playgroud)
..我知道没有这样的文件.
我下载了最新的Qt SDK框架,但是找不到添加这些API的方法.我正在使用Qt creator IDE.
有没有办法让多媒体功能可以作为插件或其他方式工作?
谢谢.
有什么方法可以找到迭代器指向的容器吗?具体来说,我希望能够找到std::vector
特定的指向,std::vector::iterator
以便我可以检查范围,而不必实际传递对该向量的引用.
如果(我怀疑)答案是否定的,为什么不呢?
编辑:感谢您提供一些快速且(大部分)准确的答案.Evan Teran指甲.我根本没有考虑优化,但现在很明显.
有几个人问我想做什么.这没什么特别重要的.我有一个对象,它用向量和指向向量的迭代器初始化.如果我可以使用迭代器初始化对象,这将是可爱和方便的,因为然后我可以将vector::iterator
s直接转换为此对象(这听起来很奇怪,但在特定情况下确实有意义).但它根本不重要.
我不清楚以下情况.
首先,这段代码编译得很好:
#include <vector>
typedef struct{
int x1,x2,x3,x4;
} ints;
typedef std::vector<ints> vec;
int main(){
vec v;
ints a = {0,1,2,3};
v.push_back(a);
}
Run Code Online (Sandbox Code Playgroud)
以下代码几乎相同:
#include <vector>
typedef std::vector<int[4]> vec;
int main(){
vec v;
int a[4] = {0,1,2,3};
v.push_back(a);
}
Run Code Online (Sandbox Code Playgroud)
但它会抛出我将在最后包含的极长的错误输出.为什么编译器对这两个程序的处理方式如此不同?这绝对不直观.
这是我的系统上使用g ++编译时抛出的编译器错误:
[mattg@pigott Test]$ g++ test2.cpp -o test2
In file included from /usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/i586-redhat-linux/bits/c++allocator.h:34,
from /usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/bits/allocator.h:48,
from /usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/vector:62,
from test2.cpp:2:
/usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/ext/new_allocator.h: In member function ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Tp*, const _Tp&) [with _Tp = int [4]]’:
/usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/bits/stl_vector.h:737: instantiated from ‘void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with …
Run Code Online (Sandbox Code Playgroud) 最近我注意到以下陈述并非如此std::string s
.
s.max_size() == s.get_allocator().max_size();
Run Code Online (Sandbox Code Playgroud)
我发现这很有意思,默认情况下std::string
会使用std::allocator<char>
它具有理论极限size_type(-1)
(是的,我知道我假设2的补码,但这与实际问题无关).我知道实际的限制将远远小于此.在典型的32位x86系统上,内核将占用2GB(可能是1GB)的地址空间,从而留下更小的实际上限.
无论如何,GNU libstdc ++ std::basic_string<>::max_size()
似乎返回相同的值,无论它使用什么分配器(如类似1073741820
).
所以问题仍然存在,为什么不std::basic_string<>::max_size()
回归get_allocator().max_size()
呢?在我看来,这是假设的上限.如果分配很短,它只会扔一个std::bad_alloc
,所以为什么不尝试?
这更像是一种好奇心,我只是想知道为什么这两者至少在这一个实现中被单独定义.
我正在使用PHP和mongodb开发一个网站.我用PECL-mongo访问mongodb ,并且遇到了烦恼.我时不时地得到这样的错误(我已经对这些路径进行了匿名)
Fatal error: Uncaught exception 'MongoCursorException' with message 'couldn't get response header' in
/PATH/index.php:38 Stack trace: #0
/PATH/index.php(38): MongoCursor->rewind() #1
/PATH/template.inc(29): get_sidebar() #2
/PATH/index.php(13):
require_once('PATH/...') #3 {main} thrown in PATH/index.php on line 38
Run Code Online (Sandbox Code Playgroud)
根据文档,这意味着:
驱动程序无法从数据库中获取回复标头,因此它放弃了.检查数据库是否仍在运行并且网络已连接,然后再次尝试查询.
但我知道数据库已启动,因为我在我自己的机器上本地执行环回.没有与外界联系.
再试一次经常有效.这可能是PHP的mongo驱动程序中的一个错误吗?这可能是一个"错误编译"的问题(我从源代码编译,但有非常良性的标志,-march=native -O2
)?
谁看过这个吗?
搜索周围,我只看到一些愚蠢的Facebook游戏的引用有相同的错误.
编辑:我刚刚将我的PECL驱动程序降级到1.1.4版本,到目前为止,问题似乎已经消失.所以这可能只是1.2.x系列中的一个错误.如果有人能够对它有所了解,那就太好了.
编辑:我在这里没有做任何复杂的事情,有问题的代码看起来像这样:
$m = new Mongo();
$collection = $m->my_db->collection;
$results = $collection->find(array("favorite"=>true))->limit(5);
Run Code Online (Sandbox Code Playgroud)