在 Objective C 中编写网络服务器——上传较大文件时获取 SIGPIPE 调用
我正在为音乐共享应用程序编写一个网络服务器...当我有一个大文件(即 mp3)时,这不起作用。它因 SIGPIPE 错误代码而崩溃。我发送的标头有“连接:关闭”——但我认为这会等到下载完成后关闭连接。我知道这可能应该分叉到一个线程中,但为了测试我想让它同步工作。
NSData *fileData =[NSData dataWithContentsOfFile:filePath];
CFHTTPMessageRef response =
CFHTTPMessageCreateResponse(
kCFAllocatorDefault, 200, NULL, kCFHTTPVersion1_1);
CFHTTPMessageSetHeaderFieldValue(
response, (CFStringRef)@"Content-Type", (CFStringRef)@"audio/mpeg");
CFHTTPMessageSetHeaderFieldValue(
response, (CFStringRef)@"Connection", (CFStringRef)@"close");
CFHTTPMessageSetHeaderFieldValue(
response,
(CFStringRef)@"Content-Length",
(CFStringRef)[NSString stringWithFormat:@"%ld", [fileData length]]);
CFDataRef headerData = CFHTTPMessageCopySerializedMessage(response);
@try
{
[fileHandle writeData:(NSData *)headerData];
[fileHandle writeData:fileData];
}@catch (NSException *exception)
{
// Ignore the exception, it normally just means the client
// closed the connection from the other end.
}
I am writing a webserver for a music sharing app ... when I have a large file (i.e an mp3) this does not work. It crashes on SIGPIPE error code. The header I am sending has "Connection: close" -- but I assumed this would wait until after the download finishes to close the connection. I know this should probably be forked into a thread but for testing i want to get it working synchronously.
NSData *fileData =[NSData dataWithContentsOfFile:filePath];
CFHTTPMessageRef response =
CFHTTPMessageCreateResponse(
kCFAllocatorDefault, 200, NULL, kCFHTTPVersion1_1);
CFHTTPMessageSetHeaderFieldValue(
response, (CFStringRef)@"Content-Type", (CFStringRef)@"audio/mpeg");
CFHTTPMessageSetHeaderFieldValue(
response, (CFStringRef)@"Connection", (CFStringRef)@"close");
CFHTTPMessageSetHeaderFieldValue(
response,
(CFStringRef)@"Content-Length",
(CFStringRef)[NSString stringWithFormat:@"%ld", [fileData length]]);
CFDataRef headerData = CFHTTPMessageCopySerializedMessage(response);
@try
{
[fileHandle writeData:(NSData *)headerData];
[fileHandle writeData:fileData];
}@catch (NSException *exception)
{
// Ignore the exception, it normally just means the client
// closed the connection from the other end.
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Web 服务器必须应对客户端提前关闭连接的情况——也许它已经足够了,或者页面加载或下载被取消。即使服务器写入正确,也可能发生这种情况。您看过对话的数据包捕获吗?
A web server has to cope with the case where the client closes the connection early -- perhaps it has enough, or the page load or download was canceled. This can happen even when the server is written correctly. Have you looked at a packet capture of the conversation?
您应该查看 如何防止 SIGPIPE(或处理它们)正确)。
这有点重复,但基本上在您的应用首次启动时使用
signal(SIGPIPE, SIG_IGN);
。这将防止发出 SIGPIPE 信号(即您的应用程序不会崩溃)。当您想在本地处理问题时,通常会这样做。您可以通过执行以下操作在本地进行检查:您还可以使用
NSStream
的streamError
或streamStatus
属性。You should check out How to prevent SIGPIPEs (or handle them properly).
This is a bit of a rehash, but basically use
signal(SIGPIPE, SIG_IGN);
when your app first launches. This will prevent the SIGPIPE from being signaled (i.e. your app won't crash). You usually do this when you want to handle the problem locally. You can check locally by doing something like:You can additionally check for errors using
NSStream
'sstreamError
orstreamStatus
properties.虽然你确实应该处理 SIGPIPE。但我猜你为什么得到它是因为你在发送数据之前没有检查请求方法。
下载器很可能会先发送 HEAD 请求来获取内容长度和其他信息。
当收到 HEAD 请求时,不应调用 [fileHandle writeData:fileData]。
我猜您正在使用 此处的 HTTPServer 代码< /a>.如果是这样,您可以这样做:
除此之外,您可能还需要处理范围请求以避免 SIGPIPE。也许还有其他东西。编写一个 HTTP 服务器来为现实世界的请求者提供服务并不容易。
Though you really should deal with SIGPIPE. But I guess why you get it is because you didn't check request method before sending data.
It is very possible that a downloader will send a HEAD request first to get the content length and other information.
When you get a HEAD request, you should not call [fileHandle writeData:fileData].
I guess you are using the HTTPServer code from here. If so, you can just do this:
Other than that, you may also need to cope with range request to avoid SIGPIPE. And maybe other stuff. It is not easy to write a HTTP server to serve real world requester.