#define SOCKET_PORT 9345 (服务器端口号)
#define SOCKET_IP @"222.137.116.11" (ip地址)
//打开socket连接 长连接 双向的 (只需要该变 端口号 和 ip地址)
- (void) connectToServer
{
//self 一个任意指针的数据,可以用在创建CFSocket对象时相关联。这个指针被传递给所有的上下文中定义的回调。
CFSocketContext CTX = {0, self, NULL, NULL, NULL};
_socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM,
IPPROTO_TCP, kCFSocketConnectCallBack, TCPServerConnectCallBack,
&CTX);
if (NULL == _socket)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@""
message:@"创建套接字失败" delegate:nil cancelButtonTitle:@"关闭"
otherButtonTitles:nil];
[alert show];
[alert release];
}
//sockaddr_in 配置socket的连接信息
struct sockaddr_in addr4;
//初始化addr4的内存
memset(&addr4, 0, sizeof(addr4));
//bzero(&addr4, sizeof(addr4));
addr4.sin_len = sizeof(addr4);
//AF_INET ipv4
addr4.sin_family = AF_INET;
//将一个无符号短整型数值转换为网络字节序,即大端模式(big-endian)
addr4.sin_port = htons(SOCKET_PORT);
//将一个点分十进制的IP转换成一个长整数型数INET_ADDR()。
addr4.sin_addr.s_addr = inet_addr([SOCKET_IP UTF8String]);
// 把sockaddr_in结构体中的地址转换为Data
CFDataRef address = CFDataCreate(kCFAllocatorDefault, (UInt8 *)&addr4, sizeof(addr4));
// address CFDataRef类型的包含上面socket的远程地址的对象
CFSocketConnectToAddress(_socket, address, -1);
CFRunLoopRef cfrl = CFRunLoopGetCurrent();// 获取当前线程的循环
//创建一个循环,但并没有真正加如到循环中,需要调用CFRunLoopAddSource
CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(kCFAllocatorDefault, _socket, 0);
//
CFRunLoopAddSource(cfrl, source, kCFRunLoopCommonModes);
CFRelease(source);
}
//启动连接服务器后,会回调此方法
static
void TCPServerConnectCallBack(CFSocketRef socket, CFSocketCallBackType
type, CFDataRef address, const void *data, void *info)
{
// 当socket为kCFSocketConnectCallBack时,失败时回调失败会返回一个错误代码指针(data),其他情况返回NULL
if (data != NULL)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@""
message:@"连接失败" delegate:nil cancelButtonTitle:@"关闭"
otherButtonTitles:nil];
[alert show];
[alert release];
return;
}
//info 跟CFSocketContext CTX = {0, self, NULL, NULL, NULL};
//第二个参数对应。
LPSocketEngine *infoObject = (LPSocketEngine *)info;
[infoObject userLogin];
//其效果与 NSThread 的 detachNewThreadSelector:toTarget:withObject: 是一样的。
[infoObject performSelectorInBackground:@selector(readStream) withObject:nil];
}