美文网首页
Socket学习

Socket学习

作者: orilme | 来源:发表于2017-09-06 21:55 被阅读83次

一、 Socket介绍

来由:多个TCP连接或多个应用程序进程可能需要通过同一个TCP协议端口传输数据。为了区别不同的应用程序进程和连接,计算机操作系统为应用程序与TCP/IP协议交互提供了套接字(Socket)接口。应用层可以和传输层通过Socket接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。

Socket又称为“套接字”,是系统提供的用于网络通信的方法。Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。

建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket,另一个运行于服务器端,称为ServerSocket。套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。

Socket可以支持不同的传输层协议(TCP或UDP),当使用TCP协议进行连接时,该Socket连接就是一个TCP连接,UDP连接同理。

2.png

二、Socket、TCP/IP和Http的联系和区别

HTTP协议是基于TCP连接的。
TCP/IP是传输层协议,主要解决数据如何在网络中传输;
而HTTP是应用层协议,主要解决如何包装数据。

在传输数据时候可以只是用TCP/IP,但是这样没有应用层,无法识别传输的数据类容,这样是没有意义的,如果想使传输的数据有意义,则必须使用应用层协议,HTTP就是一种,WEB使用它封装HTTP文本信息,然后使用TCP/IP协议传输到网络上。

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,是它的一组接口。通过Socket,我们才能使用TCP/IP协议。

Socket和HTTP还有一个区别是Socket一旦建立连接,服务器可以主动将数据传输给客户端;而HTTP则需要客户端先向服务器发送请求之后才能将数据返回给客户端。但实际上Socket建立之后因为种种原因,会导致断开连接,其中一个原因就是防火墙会断开长时间处于非活跃状态的连接,因此需要轮询高速网络,这个连接是活跃的。

1.jpg

(附1:网络七层协议由下往上分别为物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。其中物理层、数据链路层和网络层通常被称作媒体层,是网络工程师所研究的对象;传输层、会话层、表示层和应用层则被称作主机层,是用户所面向和关心的内容。)
(附2:TCP/IP五层模型的协议分为:应用层、传输层、网络层、数据链路层和物理层)

12.png

三、Socket在iOS中的使用

  1. 第三方AsyncSockets的使用
#import <Foundation/Foundation.h>
#import "AsyncSocket.h"

enum{
    SocketOfflineByServer,
    SocketOfflineByUser,
};

@interface SocketSingleton : NSObject<AsyncSocketDelegate>

@property (nonatomic, strong) AsyncSocket    *socket;       // socket
@property (nonatomic, copy  ) NSString       *socketHost;   // socket的Host
@property (nonatomic, assign) UInt16         socketPort;    // socket的prot

@property (nonatomic, retain) NSTimer        *connectTimer; // 计时器

+ (SocketSingleton *)sharedInstance;

-(void)socketConnectHost;// socket连接

-(void)cutOffSocket;// 断开socket连接

-(void)socketSendData:(NSData *) data;// socket发送数据

@end
#import "SocketSingleton.h"

@implementation SocketSingleton

+(SocketSingleton *) sharedInstance {
    static SocketSingleton *sharedInstace = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstace = [[self alloc] init];
    });
    return sharedInstace;
}

// socket连接
-(void)socketConnectHost {
    self.socket    = [[AsyncSocket alloc] initWithDelegate:self];
    NSError *error = nil;
    BOOL isConnect = [self.socket connectToHost:self.socketHost onPort:self.socketPort withTimeout:-1 error:&error];;
    if (isConnect) {
        NSLog(@"socket连接成功");
    }else {
        NSLog(@"socket连接失败");
    }
}

// socket发送数据
-(void)socketSendData:(NSData *) data {
    [self.socket writeData:data withTimeout:-1 tag:1];//-1不设置超时
}

// 连接成功回调
-(void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port {
    NSLog(@"socket连接成功");
    [self.socket readDataWithTimeout: -1 tag: 0];
    self.connectTimer = [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(longConnectToSocket) userInfo:nil repeats:YES];
    [self.connectTimer fire];
}

// 心跳连接
-(void)longConnectToSocket{
    // 根据服务器要求发送固定格式的数据,假设为指令@"longConnect",但是一般不会是这么简单的指令
    NSData   *dataStream  = [@"longConnect" dataUsingEncoding:NSUTF8StringEncoding];
    [self.socket writeData:dataStream withTimeout:-1 tag:1];//-1不设置超时
}

-(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
    NSString *msg = [[NSString alloc] initWithData: data encoding:NSUTF8StringEncoding];
    NSDictionary *dic = @{@"message":msg};
    [[NSNotificationCenter defaultCenter] postNotificationName:@"SOCKETREAGSUCCESS" object:nil userInfo:dic];
    
    [self.socket readDataWithTimeout: -1 tag: 0];
}

-(void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag{
    // [self addMessage:[NSString stringWithFormat:@"发送了"]];
}

-(void)onSocketDidDisconnect:(AsyncSocket *)sock{
    NSLog(@"socket断开连接 %ld",sock.userData);
    if (sock.userData == SocketOfflineByServer) {
        // 服务器掉线,重连
        [self socketConnectHost];
    }else if (sock.userData == SocketOfflineByUser) {
        // 如果由用户断开,不进行重连
        return;
    }
}

// 切断socket
-(void)cutOffSocket{
    self.socket.userData = SocketOfflineByUser;
    [self.connectTimer invalidate];
    [self.socket disconnect];
}

@end
  1. 用C语言实现Socket

1、Socket调用库函数主要有:

创建套接字 
Socket(af,type,protocol)

建立地址和套接字的联系 
bind(sockid, local addr, addrlen)

服务器端侦听客户端的请求 
listen( Sockid ,quenlen)

建立服务器/客户端的连接 (面向连接TCP) 
    客户端请求连接 
    Connect(sockid, destaddr, addrlen)
    服务器端等待从编号为Sockid的Socket上接收客户连接请求 
    newsockid=accept(Sockid,Clientaddr, paddrlen)

发送/接收数据 
    面向连接:     
    send(sockid, buff, bufflen) 
    面向无连接: 
    sendto(sockid,buff,…,addrlen) 
    recvfrom( )

释放套接字      
close(sockid)

四、其他

iOS中Socket编程的方式:
BSD Socket:
BSD Socket 是UNIX系统中通用的网络接口,它不仅支持各种不同的网络类型,而且也是一种内部进程之间的通信机制。而iOS系统其实本质就是UNIX,所以可以用,但是比较复杂。
CFSocket:
CFSocket是苹果提供给我们的使用Socket的方式。
AsyncSocket:
第三方开源库,首选方式,也是在开发项目中经常会用到的。
以后有机会慢慢学习。

参考文章:iOS学习之Socket使用简明教程- AsyncSocket
项目地址: SocketDemo

相关文章

  • 网络编程

    python学习笔记-网络编程 socket编程: socket()函数:socket.socket([famil...

  • #Socket回顾学习笔记

    Socket学习笔记 Socket基础知识 背景 Socket概念 Socket 又称"套接字",是系统提供的用于...

  • iOS#GCDAsyncSocket使用

    背景 最近在开发使用Socket,重新复习了socket基本知识,文章如下: #Socket回顾学习笔记UDP G...

  • HTTPS的理解

    1.Socket?后学习---------------------------------------------...

  • iOS_环信

    对于环信(即时聊天)分为三个方面学习: 1,Socket的网络通信,Socket相关难点理解(详见——Socket...

  • socket学习

    参考书籍《python核心编程第二版》 原文由于采用python2的版本,所以input函数采用的是raw_inp...

  • Socket学习

    一、 Socket介绍 来由:多个TCP连接或多个应用程序进程可能需要通过同一个TCP协议端口传输数据。为了区别不...

  • Socket学习

    一、什么是Socket编程 Socket是进程通讯的一种方式,即调用这个网络库的一些API函数实现分布在不同主机的...

  • Socket学习

    socket是网络间进程通信的一种实现方式。 下图就是socket的原理图。 那么socket在哪里呢?又是服务于...

  • socket学习

    一、什么是socket 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket ...

网友评论

      本文标题:Socket学习

      本文链接:https://www.haomeiwen.com/subject/ufppjxtx.html