iOS APP 开发 OC 第十一天,创建socket并连接伺服器

tags: OC 30 day

1. 导入头文件

#import <sys/socket.h>#import <netinet/in.h>#import <arpa/inet.h>

2. 创建 socket


创建时,看到系统提示要三个参数,但是实在是看不懂?
让我们来google一下,刚好看到了这一篇翻转工作室的文章

函数原型

int scoket(int domain,int type,int protocol); 

domain 参数

参数 domain 或称为 family,是用来选择使用哪一种通讯协定的家族系列,domain 可选择下列之一:

AF_UNIX:Unix Internet Protocol。此通讯家族并不是真正的网路通讯协定,而是用来作 Unix 作业系统中,各程序(Process)之间的通讯使用。一般使用在回授(Loopback)传输提供者,而其应用在主机内程序之间的通讯。AF_INET:Internet Protocol。此为 TCP/IP 的 Internet 通讯协定,传输提供者可能是 TCP 或 UDP,也是本章讨论的重点。AF_NS:Xerox NS Protocol。此为 Xerox 公司发展的通讯协定。AF_IMPLINK:Interface Message Protocol。此为一种智慧型的分封交换节点协定,这些节点都是使用点对点的连接方式,一般使用在租用电话线路来作资料传输使用。(不在本章讨论範围)

其中『AF_』代表 Address Family,有些系统使用『PF_』(Protocol Family),两者是相通的。domain 参数也如同 sockadd_in 资料结构中的 sin_family 参数一样。

type 参数

参数 type 是设定该 Socket 的类型,可选择下列类型之一:

SOCK_STREAM:Stream Socket。传输提供者提供一个虚拟电路服务(TCP)。SOCK_DGRAM:Datagram Socket。提供电报传输服务(UDP)。SOCK_RAW:Raw Socket。通讯协定型态在传输层之下,譬如,在 AF_INET(传输层为 TCP 或 UDP)模式,SOCK_RAW 的通讯协定可以是 IP(Internet Protocol)或 ICMP(Internet Control Message Protocol)。SOCK_SEQPACKET:Sequenced Packet Socket。提供虚拟电路(TCP)并附有维护讯息的功能。

protocol 参数

参数 protocol 是在某一个 domain 之下,选择所要哪一种协定。例如选定 AF_INET domain 系列时,所使用的协定可以是 TCP、UDP 或 IP中的一种。但当设定 domain 和 type 值时,对于所使用的协定大多已经指定完成,因此 protocol 的值一般都设定为0。但有一特殊情况,如果 Socket 的型态是 SOCK_RAW 时,必须在参数中指定它的上层协定为 TCP、UDP、IP 或 ICMP。

注意
type 与 protocol不可以随意组合,如SOCKET_STREAM不可以跟IPPROTO_UDP组合。当地三个参数为0时,会自动选择地=个参数类型对应默认协议。

大概了解以上的资料,我简单整理出

//第一个参数 domain 协议 指定IPv4//第二个参数 type socket的类型 流socket 数据报socket//第三个参数 protocol 协议//返回值 如果创建成功返回的是socket的描述符,失败-1

我们来实践看看吧

//1.    创建Socket//第一个参数 domain 协议 指定IPv4//第二个参数 type socket的类型 流socket 数据报socket//第三个参数 protocol 协议//返回值 如果创建成功返回的是socket的描述符,失败-1int clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

3. 连接伺服器


connect要三个参数,但是依然是看不懂?。
于是就交给google大神吧。

参数一:套接字描述符
参数二:指向数据结构sockaddr的指针,其中包含目的端口与IP位址
参数三:参数二socketaddr的长度,可以通过sizeof(struct sockaddr)获得

返回值
成功则返回0,失败返回非0; 错误码 GetLastError()

错误代码

EBADF 参数sockfd 非合法socket处理代码
EFAULT 参数serv_addr指针指向无法存取的内存空间
ENOTSOCK参数sockfd为一 文件描述词,非socket。
EISCONN 参数sockfd的socket已是连线状态
ECONNREFUSED 连线要求被server端拒绝。
ETIMEDOUT 企图连线的操作超过限定时间仍未有响应。
ENETUNREACH 无法传送数据包至指定的主机。
EAFNOSUPPORT sockaddr结构的sa_family不正确。
EALREADY socket为不可阻断且先前的连线操作还未完成。

我们来实践看看吧

//2.   连接伺服器    //第一个参数 socket的描述符    //第二个参数 结构体 ip地址与端口    //第三个参数 结构体的长度 sizeof    //返回值 成功0 失败非0    struct sockaddr_in addr;    addr.sin_family = AF_INET;    addr.sin_addr.s_addr = inet_addr("127.0.0.1");    connect(clientSocket, &addr, sizeof(addr));    [self setUpViews];

然后会跳出一个警告

表示type不匹配,所以我们要转型

    //2.   连接伺服器    //第一个参数 socket的描述符    //第二个参数 结构体 ip地址与端口    //第三个参数 结构体的长度 sizeof    //返回值 成功0 失败非0    struct sockaddr_in addr;    addr.sin_family = AF_INET;    addr.sin_addr.s_addr = inet_addr("127.0.0.1");    connect(clientSocket, (const struct sockaddr *)&addr, sizeof(addr));

完整的代码:

    //1.    创建Socket        //第一个参数 domain 协议 指定IPv4    //第二个参数 type socket的类型 流socket 数据报socket    //第三个参数 protocol 协议    //返回值 如果创建成功返回的是socket的描述符,失败-1    int clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);        //2.   连接伺服器    //第一个参数 socket的描述符    //第二个参数 结构体 ip地址与端口    //第三个参数 结构体的长度 sizeof    //返回值 成功0 失败非0    struct sockaddr_in addr;    addr.sin_family = AF_INET;    addr.sin_addr.s_addr = inet_addr("127.0.0.1");    addr.sin_port = htons(12345);        int result = connect(clientSocket, (const struct sockaddr *)&addr, sizeof(addr));        if (result == 0){        NSLog(@"成功");    }else{        NSLog(@"失败");    }    

接下来连接伺服器就可以运行啰。


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章