我正在使用cocoaAsyncSocket库开发用于iOS和OSX的Web代理,但遇到了问题。我能够接受来自客户端的多个连接,解析标头,通过端口80/443连接到目标,并开始接收数据,同时将数据传递回客户端套接字。但是,我遇到的问题是,使用方法readDataToLength:x时,在完成读取内容之前,服务器套接字似乎已关闭,但是,如果我只使用readDataWithTimeout,则一切正常,并且页面将加载。
使用curl通过我的代理服务器,我可以看到部分接收了数据,但是连接通过
关闭transfer closed with 12 bytes remaining to read
* stopped the pause stream!
* Closing connection 0
curl: (18) transfer closed with 12 bytes remaining to read
但是委托方法
socket:(GCDAsyncSocket *)sock didReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)tag
告诉我它已经完成了12字节的部分读取,因此读取似乎已经完成。
-(void)socket:(GCDAsyncSocket *)sock didReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)tag {
NSLog(@"READ PARTIAL DATA %lu with tag: %lu",partialLength, tag);
[sock readDataToLength:partialLength withTimeout:3 tag:tag];
}
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
ConnectionData *socketData;
@synchronized (self) {
socketData = [self getConnectionDataForSocket:sock];
}
if (tag == CLIENT_SOCK_READ) {
//NSLog(@"READ FROM CLIENT");
if (!socketData.serverSocket){
//We dont have a server socket yet, assume that we are reading the header data.
NSString *headers = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
//Decide if we have a http or ssl connection
if ([headers containsString:@"CONNECT"]) {
//TLS SESSION
NSString* hostToConnect = [self extractStringFromString:headers from:@"CONNECT " to:@":"];
NSError *connectError;
GCDAsyncSocket *serverSock = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:[self socketsDispatchQueue]];
@synchronized (self) {
socketData.serverSocket = serverSock;
}
if (![serverSock connectToHost:hostToConnect onPort:443 withTimeout:10 error:&connectError]){
NSLog(@"Failed to connect to host: %@", [connectError debugDescription]);
}
NSString *tlsClientResponse = @"HTTP/1.0 200 Connection established\r\n\r\n";
[[socketData clientSocket]writeData:[tlsClientResponse dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:CLIENT_SOCK_WRITE];
} else {
NSString *hostToConnect = [self extractStringFromString:headers from:@"http://" to:@"/"];
NSString *newheaderLine = [self prepareHttpHeader:headers];
//Rewite headers
NSError *connectError;
GCDAsyncSocket *serverSock = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:[self socketsDispatchQueue]];
@synchronized (self) {
socketData.serverSocket = serverSock;
}
if (![serverSock connectToHost:hostToConnect onPort:80 withTimeout:10 error:&connectError]){
NSLog(@"Failed to connect to host: %@", [connectError debugDescription]);
}
[socketData.serverSocket writeData:[newheaderLine dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:false] withTimeout:10 tag:SERVER_SOCK_WRITE];
}
} else {
[socketData.serverSocket writeData:data withTimeout:3 tag:SERVER_SOCK_WRITE];
}
} else if (tag == SERVER_SOCK_READ){
[socketData.serverSocket readDataToLength:25 withTimeout:3 tag:SERVER_SOCK_READ];
[socketData.clientSocket writeData:data withTimeout:3 tag:CLIENT_SOCK_WRITE];
}
}
-(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
ConnectionData *socketData;
@synchronized (self) {
socketData = [self getConnectionDataForSocket:sock];
}
if (tag == SERVER_SOCK_WRITE){
[socketData.serverSocket readDataToLength:25 withTimeout:3 tag:SERVER_SOCK_READ];
} else if (tag == CLIENT_SOCK_WRITE){
[socketData.clientSocket readDataToLength:25 withTimeout:3 tag:CLIENT_SOCK_READ];
[socketData.serverSocket readDataToLength:25 withTimeout:3 tag:SERVER_SOCK_READ];
}
}
如果有人可以将我指向正确的方向,我会非常感激!