我在 GNU/Linux 下用 C 语言编程的多线程服务器中有这种奇怪的行为。当它正在发送数据时,最终会被 SIGPIPE 中断。因此,我设法忽略了 send() 中的信号并在每次操作后处理 errno。
因此,它有两种单独的发送方法,一种是一次发送大量数据(或至少尝试发送),另一种是发送几乎相似的数据量并将其分成小块。最后,我尝试用它来保持它发送数据。
do
{
total_bytes_sent += send(client_sd, output_buf + total_bytes_sent,
output_buf_len - total_bytes_sent, MSG_NOSIGNAL);
}
while ((total_bytes_sent < output_buf_len) && (errno != EPIPE));
这段丑陋的代码在某些情况下起作用,但并非总是如此。
我很确定这不是硬件或 ISP 问题,因为该服务器在六台欧洲服务器上运行,其中四台在德国,两台在法国。
有什么想法吗?
提前致谢。
编辑 1:是的,我注意到这段代码很糟糕(感谢 Jay)。我最初的意思是,无论客户端是否切断通信,这段代码都会给我一个 EPIPE。
编辑 2:我尝试使用单个 send() ,它随机给我同样的错误。这很奇怪,因为我无法发送大数据 block 。我尝试扩大发送缓冲区,但没有成功。
编辑 3:根据要求,这是一个更大的代码段。
data_buf_len = cur_stream->iframe_offset[cur_stream->iframe_num - 1] - first_offset;
data_buf = cur_stream->data;
output_buf = compose_reply(send_params, data_buf, data_buf_len, &output_buf_len);
/* Obviously, time measuring is *highly* unaccurate, only for
* design consistency purposes (it should return something).
* */
clock_gettime(CLOCK_REALTIME, &start_time);
total_bytes_sent = send(client_sd, output_buf, output_buf_len, MSG_NOSIGNAL);
clock_gettime(CLOCK_REALTIME, &stop_time);
spent_time = (((int64_t)stop_time.tv_sec * NANOSEC_IN_SEC) +
(int64_t)stop_time.tv_nsec) - (((int64_t)start_time.tv_sec * NANOSEC_IN_SEC) +
(int64_t)start_time.tv_nsec);
free(output_buf);
unload_video(cur_video);
if (total_bytes_sent < 0)
{
log_message(MESSAGE, __func__, IMSG_VIDEOSTOP, cur_video->path);
log_message(MESSAGE, __func__, IMSG_VIDEOSTOP, NULL);
}
/* Hope it will not serve >2147483647 seconds (~68 years) of video... */
return ((int)spent_time);
只有一个带有大缓冲区的 send() 调用。还有另一个例子,太大而无法放在这里,它将每个缓冲区分成较小的 block 并为每个 block 调用 send()。
最佳答案
正如 EJP 已经建议的那样,如果另一方关闭了套接字,则 EPIPE 出现。另外,我认为无论发送函数返回什么,您添加到“total_bytes_sent”的逻辑都是不正确的,因为在某些您仍然可以继续操作的情况下,发送可能会返回 -1(例如:在非阻塞套接字的情况下,您可能会在需要重试的地方收到错误号 EAGAIN)。
此外,如果 send 返回 0 并且 errno 不是 EPIPE,那么我猜你会不断循环。
编辑:您还可以检查 shutdown 是否正在套接字上调用。即使这样也可能导致这种行为。
关于c - send() 总是被 EPIPE 打断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2598488/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我正在学习Rails,并阅读了关于乐观锁的内容。我已将类型为integer的lock_version列添加到我的articles表中。但现在每当我第一次尝试更新记录时,我都会收到StaleObjectError异常。这是我的迁移:classAddLockVersionToArticle当我尝试通过Rails控制台更新文章时:article=Article.first=>#我这样做:article.title="newtitle"article.save我明白了:(0.3ms)begintransaction(0.3ms)UPDATE"articles"SET"title"='dwdwd
我正在学习如何在我的Ruby代码中使用Module.prepend而不是alias_method_chain,我注意到有些人使用send调用它(example):ActionView::TemplateRenderer.send(:prepend,ActionViewTemplateRendererWithCurrentTemplate)而其他人直接调用它(example):ActionView::TemplateRenderer.prepend(ActionViewTemplateRendererWithCurrentTemplate)而且,虽然我还没有看到任何人使用这种风格,但我从
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
我正在尝试学习Ruby词法分析器和解析器(whitequarkparser)以了解更多有关从Ruby脚本进一步生成机器代码的过程。在解析以下Ruby代码字符串时。defadd(a,b)returna+bendputsadd1,2它导致以下S表达式符号。s(:begin,s(:def,:add,s(:args,s(:arg,:a),s(:arg,:b)),s(:return,s(:send,s(:lvar,:a),:+,s(:lvar,:b)))),s(:send,nil,:puts,s(:send,nil,:add,s(:int,1),s(:int,3))))任何人都可以向我解释生成的
假设我有一个类A,里面有一些方法。假设stringmethodName是这些方法之一,我已经知道我想给它什么参数。它们在散列中{'param1'=>value1,'param2'=>value2}所以我有:params={'param1'=>value1,'param2'=>value2}a=A.new()a.send(methodName,value1,value2)#callmethodnamewithbothparams我希望能够通过传递我的哈希以某种方式调用该方法。这可能吗? 最佳答案 确保methodName是一个符号,而
最好用一个例子来解释:文件1.rb:deffooputs123end文件2.rb:classArequire'file1'endA.new.foo将给出错误“':调用了私有(private)方法'foo'”。我可以通过执行A.new.send("foo")来解决这个问题,但是有没有办法公开导入的方法?编辑:澄清一下,我没有混淆include和require。另外,我不能使用正常包含的原因(正如许多人正确指出的那样)是因为这是元编程设置的一部分。我需要允许用户在运行时添加功能;例如,他可以说“run-this-app--includefile1.rb”,应用程序的行为将根据他在file1
这个问题在这里已经有了答案:关闭11年前。PossibleDuplicate:RubyblockandunparenthesizedargumentsWhatisthedifferenceorvalueoftheseblockcodingstylesinRuby?我一直认为以下只是同一件事的两种表达方式:[1,2,3].collect{|i|i*2}[1,2,3].collectdo|i|i*2end但是我在我的一个ERB模板中发现了一些奇怪的行为,这两种语法似乎在做两件不同的事情。这段代码效果很好:m))}}%>但是当我将其重写为:m))endend%>...我最终得到了我的@men
我在Sinatra应用程序上使用send_file:get'/update/dl/:upd'dofilename="/uploads/#{params[:upd]}"send_file(filename,:filename=>"t.cer",:type=>"application/octet-stream")end/uploads/文件夹不是公开的,它在应用程序目录中。当我尝试在Chrome中访问localhost:4567/update/dl/some_file时,它会返回404,就像在Firefox中一样,当看到标题时,它是404。但是如果我尝试使用Safari,它下载文件。所以我
我正在尝试向浏览器发送多个文件。我不能像下面的代码一样为每条记录调用send_data,因为我收到双重渲染错误。根据thispost我需要创建文件并压缩它们,以便我可以在一个请求中发送它们。@records.eachdo|r|ActiveRecord::Base.include_root_in_json=true@json=r.to_jsona=ActiveSupport::MessageEncryptor.new(Rails.application.config.secret_token)@json_encrypted=a.encrypt_and_sign(@json)send_da