SocketRocket 支持 ipv6 的 ip 地址

512 阅读1分钟

前言

首先 SocketRocket 0.6.0 是支持 ipv6的,不过是对域名的支持。 对 ip地址形式 是没有做处理的。后台在接收到请求时,如果没有检查到 [ ] ,则会认为你是 ipv4 或者 是域名,于是报错:

Error Domain=SRWebSocketErrorDomain Code=2132 "Received bad response code from server: 400." UserInfo={NSLocalizedDescription=Received bad response code from server: 400., HTTPResponseStatusCode=400}

Bug

经过抓包发现,socket发送的http请求形式是这样的: ws:xxxx::xxx:xxxx:xxxx:xxxx:8001/websocket/sd 由于 公司 使用的是ip地址,正常区分ipv6的 host 和 port ,是需要像[host]:port 这样来进行请求的。

解决方案

Socket内部发送的Http请求,构造底层 Request的地方:

CFHTTPMessageRef SRHTTPConnectMessageCreate(NSURLRequest *request,
                                            NSString *securityKey,
                                            uint8_t webSocketProtocolVersion,
                                            NSArray<NSHTTPCookie *> *_Nullable cookies,
                                            NSArray<NSString *> *_Nullable requestedProtocols)

核心: 改动 Request Head 中 Host 的配置

static NSString *_SRHTTPConnectMessageHost(NSURL *url)
{
    NSString *host = url.host;
    if ([host containsString:@":"]) {
        // ipv6 ip 地址形式的兼容
        host = [NSString stringWithFormat:@"[%@]",host];
    }
    if (url.port) {
        host = [host stringByAppendingFormat:@":%@", url.port];
    }
    return host;
}

感谢

感谢大佬的 SocketRocket简单使用与源码解析,让我对的整个过程有了更深的了解。