Socket 网络编程

1.TCP/IP、UDP

TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议。是一个工业标准的协议集,它是为广域网(WANs)设计的。
UDP(User Data Protocol,用户数据报协议)是与TCP相相应的协议。它是属于TCP/IP协议族中的一种。
以下这张图。表明了这些协议的关系。如图TCP/IP协议族包含运输层、网络层、链路层:
协议关系

2.Socket

在图1中,我们没有看到Socket的影子,那么它究竟在哪里呢?还是用图来说话,一目了然。
这里写图片描写叙述

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中。Socket事实上就是一个门面模式。它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说。一组简单的接口就是所有,让Socket去组织数据。以符合指定的协议。

3.使用socket

前人已经给我们做了好多的事了,网络间的通信也就简单了很多,但毕竟还是有挺多工作要做的。

曾经听到Socket编程,认为它是比較高深的编程知识,可是仅仅要弄清Socket编程的工作原理,神奇的面纱也就揭开了。
这里写图片描写叙述

一个生活中的场景。

你要打电话给一个朋友。先拨号,朋友听到电话铃声后提起电话,这时你和你的朋友就建立起了连接,就能够讲话了。等交流结束,挂断电话结束此次交谈。

生活中的场景就解释了这工作原理。或许TCP/IP协议族就是诞生于生活中。这也不一定。

4.代码演示样例

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

    @interface ViewController ()

    // client socket
    @property (nonatomic, assign) int clientSocket;

    @property (nonatomic, weak) IBOutlet UIWebView *myWebView;

    @end

    @implementation ViewController
    /**
     ======= 请求头 =======
     1> 请求行
        GET / HTTP/1.1

        GET        表示从server"拿"数据
        /          訪问server的根文件夹
        HTTP/1.1   HTTP的协议以及版本号

     2> 请求头
        Host:              要訪问的主机
        User-Agent:        用户代理,告诉serverclient的类型
        Accept:            告诉serverclient支持的数据格式
        Accept-Language:   告诉serverclient支持的语言
        Accept-Encoding:   告诉serverclient支持的解压缩类型

     HTTP请求本身的格式,是字符串格式的。最末一行,以 \n\n 结束,表示所有请求的内容发送完成,server能够处理!

提示:key 值是 HTTP 协议定义的,不能任意更改! ==========响应 =========== 1> 状态行 HTTP/1.1 200 OK HTTP/1.1 HTTP的协议以及版本号 200 状态码(404) 2XX 成功 4XX client错误 5XX server错误 2> 响应头,server告诉client的一些信息 提示:响应的信息,通常在开发“下载”功能时,才会使用,平时用不着 Date: 响应日期 Server: server的信息 // 文件长度 Content-Length: 24 3> 数据实体。从server返回的二进制数据! println("hello world!"); */ - (void)viewDidLoad { [super viewDidLoad]; // http 端口是 80 if ([self connectToHost:@"61.135.169.125" port:80]) { NSLog(@"连接成功"); } // 发送消息给 web server // 建立请求字符串 NSString *request = @"GET / HTTP/1.1\n" "Host: www.baidu.com\n" "User-Agent: iPhone AppleWebKit\n\n"; // 对结果的处理 NSString *result = [self sendAndRecv:request]; // 找 \r\n 的出现的位置 NSRange range = [result rangeOfString:@"\r\n\r\n"]; // 推断是否找到 if (range.location == NSNotFound) { NSLog(@"html 错误"); return; } NSString *html = [result substringFromIndex:range.location]; [self.myWebView loadHTMLString:html baseURL:[NSURL URLWithString:@"http://www.baidu.com"]]; } - (BOOL)connectToHost:(NSString *)host port:(int)port { // 1. socket /** 參数 domain: 协议域,AF_INET type: Socket 类型,SOCK_STREAM(流 TCP)/SOCK_DGRAM(报文。提示: 在有些公司的程序猿给server发送数据,会说:发送报文) protocol: IPPROTO_TCP。提示:假设输入0。会依据第二个參数。自己主动选择协议 返回值 socket 假设>0。就是正确的 */ self.clientSocket = socket(AF_INET, SOCK_STREAM, 0); // 2. 连接到另外一台计算机 /** 參数 1> clientsocket 2> 指向数据结构sockaddr的指针。当中包含目的端口和IP地址 C 语言中没有对象,实现都是通过结构体来实现的 3> 结构体数据长度 返回值 0 成功/其它 错误代号,非常多C语言的程序都会如此设计。原因:成功仅仅有一个。失败会有非常多种!

C 语言中,一般是非零即真 */ struct sockaddr_in serverAddress; // 1> 地址 inet_addr 能够将 ip 地址转换成整数 // 提示:在网络上的使用的非常多数据,须要做字节翻转 serverAddress.sin_addr.s_addr = inet_addr(host.UTF8String); // 2> 端口 htons 能够将端口转换成整数 // 端口号相同要做字节翻转 serverAddress.sin_port = htons(port); // 3> 协议 serverAddress.sin_family = AF_INET; // 在 C 语言中。通常传递结构体的指针同一时候,会传递结构体的尺寸 int result = connect(self.clientSocket, (const struct sockaddr *)&serverAddress, sizeof(serverAddress)); return (result == 0); } /** * 发送&接收消息 */ - (NSString *)sendAndRecv:(NSString *)msg { // 3. 发送数据给server /** 參数 1> clientsocket 2> 发送内容地址 3> 发送内容长度 4> 发送方式标志,一般为0 返回值 假设成功,则返回发送的字节数,失败则返回SOCKET_ERROR 提示:在非常多C语言框架中,会将基本数据类型进行封装。使用的时候,便于兴许框架的调整 */ // 在 UTF8 编码中。一个中文相应 3 个字节 ssize_t sendLen = send(self.clientSocket, msg.UTF8String, strlen(msg.UTF8String), 0); // 4. 从server接收数据 uint8_t buffer[1024]; // 1> 定义一个可变的二进制数据,方便拼劲 NSMutableData *dataM = [NSMutableData data]; // server返回的回车计数 int count = 0; while (count == 0) { // 2> 接收数据 ssize_t recvLen = recv(self.clientSocket, buffer, sizeof(buffer), 0); [dataM appendBytes:buffer length:recvLen]; // 通过跟踪,\r\n\r\n 须要继续等待,\r\n 表示传输结束 // 取末尾一个字节 uint8_t lastByte = buffer[recvLen - 1]; // 取倒数第三个字节 uint8_t preLastByte = buffer[recvLen - 3]; if (lastByte == '\n' && preLastByte != '\n') { count++; } } return [[NSString alloc] initWithData:dataM encoding:NSUTF8StringEncoding]; } /** * 断开连接 */ - (void)disconnect { // 5. 关闭连接 close(self.clientSocket); } @end

5. 延伸阅读

1.Linux socket 编程:
http://www.ibm.com/developerworks/cn/education/linux/l-sock/l-sock.html
2. 网络编程学习笔记一:Socket编程:
http://blog.csdn.net/gneveek/article/details/8699198

posted @ 2017-07-28 08:17  brucemengbm  阅读(146)  评论(0编辑  收藏  举报