- 接受消息
- 转发消息
- ProtocolBuffer
TCP/UDP的概念和区分
- 进行Socket 编程,常见使用的协议UDP/TCP
- TCP:
传输控制协议,是专门设计用于在不可靠的因特尔网上提供可靠的,端到端的字节流通信的协议,他是一种面向连接的协议,TCP连接是字节流而非报文流-
TCP 在传输数据是,传输的是字节流,在读取消息时,需要知道数据的长度,否则就会出现读取不完整或者读取过多的情况,因此读取方法要求发送方传入本次读取消息长度!
图片.png
-
- UDP:
用户数据报协议不需要连接,不可靠
- TCP:
-
举例区分- TCP 类似于打电话,双方直接通信
- UDP类似于发短信,双方发出消息后等待别人的回复
- 建立连接时所需要的寻址信息为IP地址和端口号
- IP地址: 用于区分那一台计算器需要和我建立连接
- 端口号: 用于区分那一个应用程序和我建立连接
- 消息类型
- 结构体: 客户端把消息封装成结构体,转成Data类型->字节,发给服务器,(服务器解析出解析)服务器要是Java的话(因为不常用结构体!So...)
- SOAP: XML描述,数据大
- Json: 序列化,反序列化
- ProtocolBuffer (PB,GPB)谷歌开源,跨平台,非常方便序列化,反序列化, 消息大小XML的20分之一,是二进制序列化的10分之一,Json的十分之一
- BSD Socket 是UNIX系统中通用的网络接口!它不仅支持各种不同的网络类型,而且是一种内部进程之间的通信机制,iOS也可以用C语言函数
- CFSock : 是苹果官方提供的Socket编程,里面还是有很多C语言,麻烦
- AsyncSocket : 是开源的库OC版,用法很简单!两个文件.h.m
- ysocket : 是Swift目前使用的Socket编程,SwiftSocket
图片.png
cocoapods
pod 'SwiftSocket'
pod 'ProtocolBuffers-Swift'
创建SeverSocketManager文件管理Sever
import SwiftSocket
class SeverSocketManager {
fileprivate var severSocket : TCPServer = TCPServer(address: "0.0.0.0", port: 5656)
fileprivate var isSeverSocketRunning : Bool = false
fileprivate lazy var clientManagerArray : [ClientManager] = [ClientManager]()
}
开启方法 , 关闭
extension SeverSocketManager {
func startSever() ->((String , Bool)){
let flag = severSocket.listen() //开启监听
if flag.isSuccess {
isSeverSocketRunning = true
DispatchQueue.global().async { //开启新线程
while self.isSeverSocketRunning {
if let client = self.severSocket.accept(){ //循环接受ClientSocket
DispatchQueue.global().async {
self.handleClient(client) //处理接收到的ClientSocket
}
}
}
}
return ("开启成功",flag.isSuccess)
}else{
return ("开启失败",flag.isFailure)
}
}
func stopSever(){
isSeverSocketRunning = false
}
}
- 处理ClientSocket
extension SeverSocketManager {
fileprivate func handleClient (_ client : TCPClient){
let mgr = ClientManager(tcpClient: client)
mgr.delegate = self
//保存客户端
clientManagerArray.append(mgr)
//用Client开始接受消息(读取消息)
mgr.startRedMsg()
}
}
extension SeverSocketManager : ClientManagerDelegate{
func deleteClient(clientManager: ClientManager) {
clientManager.tcpClient.close()
guard let index = clientManagerArray.index(of: clientManager) else {return}
clientManagerArray.remove(at: index)
print(clientManagerArray.count)
}
func sendMsgClientTo(_ data: Data) {
let str = String(data: data, encoding: .utf8)
print(str!)
for mgr in clientManagerArray{
mgr.tcpClient.send(data: data)
}
}
}
创建ClientManager管理Client
import SwiftSocket创建代理用来给外界提供消息和移除断开连接的Client
protocol ClientManagerDelegate : class{
func sendMsgClientTo(_ data : Data)
func deleteClient(clientManager : ClientManager)
}
class ClientManager: NSObject {
weak var delegate : ClientManagerDelegate?
var tcpClient : TCPClient
fileprivate var isClientConnected : Bool = false //连接状态
fileprivate var heartTimeCount : Int = 0 //心跳包计时
init(tcpClient : TCPClient) {
self.tcpClient = tcpClient
}
}
- 读取消息函数
extension ClientManager{
func startRedMsg(){
//心跳包计时
let timer = Timer(fireAt: Date(), interval: 1, target: self, selector: #selector(checkHeartBeat), userInfo: nil, repeats: true)
RunLoop.current.add(timer, forMode: .commonModes)
timer.fire()
isClientConnected = true
while isClientConnected {
if let msg = tcpClient.read(4){ //读取4个字节
//读取Header的长度
let headerData = Data(bytes: msg, count: 4) //字节传承Data
var length : Int = 0
(headerData as NSData).getBytes(&length, length: 4) //获取消息的长度
//读取类型
guard let messageType = tcpClient.read(2) else { return }
let typeData = Data(bytes: messageType, count: 2) //把类型转换成Data
var type : Int = 0
(typeData as NSData).getBytes(&type, length: 2) //获取类型的长度
// print("type = \(type)") //获取类型
// print(length)
//根据长度读取真正的消息
guard let trueMsg = tcpClient.read(length) else { return }
let data = Data(bytes: trueMsg, count: length)
//1表示离开,断开连接
if type == 1{
DispatchQueue.main.async {
self.delegate?.deleteClient(clientManager: self)
}
}
else if type == 100{ //100消息类型(心跳包消息类型)
heartTimeCount = 0 //如果接收到心跳包则重置时间
let message = String(data: data, encoding: .utf8)
print(message!)
continue
}
//Data拼接转发
let totalData = headerData + typeData + data
delegate?.sendMsgClientTo(totalData)
}else{
removeClient()
}
}
}
@objc fileprivate func checkHeartBeat(){
print("-------------")
heartTimeCount += 1
if heartTimeCount >= 10 {
removeClient()
}
}
fileprivate func removeClient(){
isClientConnected = false
print("客户端断开了链接")
//从数组中删除ClientSocket
delegate?.deleteClient(clientManager: self)
}
}
- 在OS 程序中
class ViewController: NSViewController {
fileprivate lazy var severSocketManager : SeverSocketManager = SeverSocketManager()
@IBOutlet weak var messageLabel: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func start(_ sender: NSButton) {
let flag = severSocketManager.startSever()
if flag.1{
messageLabel.stringValue = "succeed"
messageLabel.textColor = .green
}else{
messageLabel.stringValue = "fail"
messageLabel.textColor = .red
}
}
@IBAction func stop(_ sender: NSButton) {
}
}```






网友评论