iOS端Socket连接、发送数据(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dolacmeng/article/details/81085905

一、Socket的应用

IM即时通讯是通过Socket的方式实现长连接,可运用于
(1)直播聊天室、礼物
(2)微信、QQ等即时聊天
(3)游戏对话、技能等

二、SOCKET原理

套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行。建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket,另一个运行于服务器端,称为ServerSocket。建立连接时所需的寻址信息为IP地址和端口号

IP地址:用于区分那一台机器需要建立连接
端口号:用于区分和哪一个应用程序建立连接

套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。

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

三、iOS端使用的Socket

简单的来说,Socket是我们使用TCP/IP 或者UDP/IP协议的一组编程接口,其介于应用层和传输层之间。传输层可以选择TCP或UDP,UDP是不可靠传输,为了保证数据的可靠性,实现起来会更加复杂,所以一般项目使用TCP即可。iOS使用Socket的常用方式有如下:
(1)BSD Socket:是UNIX系统中通用的网络接口,基于C语言,比较底层
(2)CF Socket:苹果官方提供,来自于CoreFoundation框架
(3)AsyncSocket:对BSD Socket的封装,OC语言
(4)ysocket:对BSD Socket的封装,Swift语言
在下面的Swift例子中,会使用ysocket

四、客户端(iOS程序)

(1)新建项目client
(2)将ysocket添加到项目中
这里写图片描述
(3)新建HYSocket管理类,提供socket连接、发送消息、断开连接等
(4)在HYSocket中实现init(addr : String, port : Int)初始化方法,通过地址和端口号来初始化TCPClient

class HYSocket {
    fileprivate var tcpClient : TCPClient

    init(addr : String, port : Int) {
        tcpClient = TCPClient(addr:addr, port:port)
    }
}

(5)实现connectServer()方法,实现连接Socket服务器

extension HYSocket {
    func connectServer() -> Bool {
        let temp = tcpClient.connect(timeout: 5)
        print(temp.1)
        return temp.0
    }
}

(6)在主函数中,初始化HYSocket类,并调用connectServer()进行连接

class ViewController: UIViewController {

    fileprivate lazy var socket : HYSocket = HYSocket(addr: "0.0.0.0", port: 7878)

    override func viewDidLoad() {
        super.viewDidLoad()
        if socket.connectServer() {
            print("连接上服务器")
        }
    }
}

五、服务器端(Mac OS程序)

代码:https://github.com/dolacmeng/socketConnectDemo/tree/connect/ServerDemo

六、测试连接

(1)运行服务器端(Mac程序),点击开启
这里写图片描述
(2)运行客户端(iOS程序),服务器和客户端Socket连接成功后,打印出连接成功:
这里写图片描述

连接的完整代码:https://github.com/dolacmeng/socketConnectDemo/tree/connect

七、发送消息

TCP在传输数据时,传输的是字节流,因此在读取消息时,需要知道数据的长度,否则会出现读取不完整或读取过多的情况。可以通过【长度数据+真实数据】的方式传输数据

1.在HYSocket类中,添加发送消息的方法

extension HYSocket {

    //...

    func sendMsg(data : Data){
        tcpClient.send(data: data)
    }
}

2.在HYSocket类中,继续添加发送文字消息方法

func sendMsg(message: String) {
    //1.获取消息长度
    let data = message.data(using: .utf8)!
    print(data.count)
    var length = data.count

    //将消息长度写入data
    let headerData = Data(bytes:&length, count: 4)

    //发送消息
    let totalData = headerData + data
    socket.sendMsg(data: totalData)
}

3、简单布局界面,并在相应的点击方法中,调用HYSocket对应方法:
这里写图片描述

class ViewController: UIViewController {

    fileprivate lazy var socket : HYSocket = HYSocket(addr: "0.0.0.0", port: 7878)

    @IBOutlet weak var contentTextField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()


    }

    //点击发送
    @IBAction func clickSend(_ sender: UIButton) {
        guard let content = contentTextField.text else{
            return
        }

        socket.sendMsg(message: content);
    }

    //点击连接
    @IBAction func clickConnect(_ sender: UIButton) {
        if socket.connectServer() {
            print("连接上服务器")
            socket.sendMsg(message: "您好啊,服务器");
        }
    }


    @IBAction func clickDisconnect(_ sender: UIButton) {
    }
}

服务器端读取数据核心代码:

//获取数据长度的data
let lMsgData = Data(bytes: lMsg, count: 4)  
var length : Int = 0
(lMsgData as NSData).getBytes(&length, length: 4)

//根据长度读取消息
guard let msg = tcpClient.read(length) else{
    return
}
let msgData  = Data(bytes: msg, count: length)
let msgString = String(data: msgData, encoding: .utf8)
print(msgString!)

4.测试:客户端点击连接,然后输入要发送的文字,点击发送:
这里写图片描述

八、心跳包

心跳包就是在客户端和服务器间定时通知对方自己状态的一个自己定义的命令字,按照一定的时间间隔发送,类似于心跳,所以叫做心跳包。
在本例中,在Socket连接成功后,开启一个定时服务,每隔9秒发送一次消息给服务器,跟服务器约定好心跳包的内容,将上文中的clickConnect函数修改为:

    //点击连接
    @IBAction func clickConnect(_ sender: UIButton) {
        if socket.connectServer() {
            print("连接上服务器")
            socket.startReadMsg()
            socket.sendMsg(message: "您好啊,服务器");

            //定时发送心跳包
            timer = Timer(fireAt: Date(), interval: 8, target: self, selector: #selector(sendHeartBeat), userInfo: nil, repeats: true)
            RunLoop.main.add(timer, forMode: .commonModes)
        }

    }

实现上面代码的sendHeartBeat方法

extension ViewController{
    @objc fileprivate func sendHeartBeat(){
    socket.sendHeartBeat()
    }
}

在HYSocket中,实现发送心跳包的方法

func sendHeartBeat() {
        //心跳包数据
        let heartString = "i am a heart beat"        
        //发送心跳包数据
        sendMsg(message: heartString)
    }

  
用来判断对方(设备,进程或其它网元)是否正常运行

下一篇:通过ProtocolBuffer来封住啊消息内容并发送:
https://blog.csdn.net/dolacmeng/article/details/81136635

本篇完整代码:https://github.com/dolacmeng/socketConnectDemo/tree/sendMsg

猜你喜欢

转载自blog.csdn.net/dolacmeng/article/details/81085905
今日推荐