Summary of methods for sending and receiving socket in SWIFT message

Source: Internet
Author: User
Tags sendmsg socket

The use of sockets can be very easy to achieve customer service and server long connection, and two-way data communication. But sometimes the length of the packets we send is not fixed (such as a chat system), the usual practice is to add a header information in front of the packet to let the receiver know the length of the packet. This means that the receiver receives the header information of the fixed length first, and then accepts the packet data according to the actual length defined in the header information.
The following is a chat room program to demonstrate the socket send/read the indefinite length of the message packet several methods. Socket communication Here we use a Packaged socket library (swiftsocket).

Several methods (in the chat room for example)

Method 1: Send two packets per message
The 1th packet length is fixed to 4 bytes, and the inside record is the length of the actual message packet sent later.
The 2nd package is the actual message package.
The receiver first receives the first fixed-length packet and knows the length of the data through the first packet to read the actual message packet. This way I used to write about the article, the address is: Swift-communication using sockets (with chat room sample)

(1) The relevant code for sending data is as follows:

Send a message
Func SendMessage (msgtosend:nsdictionary) {
Let Msgdata=try? Nsjsonserialization.datawithjsonobject (Msgtosend,
Options:. prettyprinted)
var len:int32=int32 (msgdata!. Length
Let Data:nsmutabledata=nsmutabledata (bytes: &len, Length:4)
self.socketclient!. Send (Data:data)
self.socketclient!. Send (data:msgdata!)
}

(2) The relevant code for receiving data is as follows:

Resolve received messages
Func readmsg ()->nsdictionary? {
Read 4 byte int as type
If let data=self.tcpclient!. Read (4) {
If data.count==4{
Let Ndata=nsdata (Bytes:data, Length:data.count)
var len:int32=0
Ndata.getbytes (&len, Length:data.count)
If let buff=self.tcpclient!. Read (Int (len)) {
Let Msgd:nsdata=nsdata (Bytes:buff, Length:buff.count)
Let msgi:nsdictionary= (try!
Nsjsonserialization.jsonobjectwithdata (MSGD,
Options:. mutablecontainers)) as! Nsdictionary
Return Msgi
}
}
}
return Nil
}


Method 2: Send only 1 packets per message. However, this package adds header information.
This is actually the integration of the above approach. The sender adds the message length to the header information (for example, a fixed size of 4 bytes) to the message packet.
The receiver reads the first 4 bytes of content, and then reads the remaining messages based on the length information obtained.

(1) The client side (Viewcontroller.swift) to send a message when the header in front of the message packet, so that only one packet sent each time. (the mode of receiving data does not change)
1

//Send Message
Func SendMessage (msgtosend:nsdictionary) {
   //Message packet
    let Msgdata = try? Nsjsonserialization.datawithjsonobject (Msgtosend,
                                                               options:. prettyprinted)
   //Message packet size
    var len:int32=int32 (msgdata!. Length)
   //message header data
    let Data:nsmutabledata=nsmutabledata (bytes: &len, Length:4)
   //header adds a true message packet
    data.appenddata (msgdata!)
   //Send merged packets
    self.socketclient!. Send (Data:data)
}

(2) The service side (Mytcpsocketserver.swift) also sends a packet containing the header information. (the mode of receiving data does not change)

Send a message
Func sendmsg (msg:nsdictionary) {
Message Packets
Let Jsondata=try? Nsjsonserialization.datawithjsonobject (MSG, Options:
nsjsonwritingoptions.prettyprinted)
Message packet size
var len:int32=int32 (jsondata!. Length
Message header Data
Let Data:nsmutabledata=nsmutabledata (bytes: &len, Length:4)
Add a true message packet after header
Data.appenddata (jsondata!)
Send merged packets
self.tcpclient!. Send (Data:data)
}

Method 3: Send only 1 packets per message. The header information is not added at the same time.
In this way the sender sends the message packages directly and no additional header information is added.
The receiving party needs to do a circular read because it does not know the actual length of the message. The fixed number of bytes per read (such as 1024 bytes), if the number of bytes read to less than 1024 bytes, then read finished.

(1) First modify the Ytcpsocket.swift and add the ReadAll () method to the TcpClient class, which enables you to automatically iterate through all messages without specifying the expected length of data.


/*
* Do not specify length to read data
*/
public func ReadAll (timeout:int =-1)->[uint8]? {
Content buffers
var data:[uint8] = [UInt8] ()
repeat{
If let TempData = Read (1024, timeout:timeout) {
To add data to a buffer every time it is read
data = data + TempData
Read End
If Tempdata.count < 1024 {
Break
}
}else{
Break
}
}while true
Return data
}

(2) Client Management class Chatuser (Mytcpsocketserver.swift) modification
The way to receive data is modified, and the message length is no longer required before sending the data, and the message packet can be sent directly.


Client Management class (easy for server to manage connected clients)
Class chatuser:nsobject{
var tcpclient:tcpclient?
var username:string= ""
var socketserver:mytcpsocketserver?

Resolve received messages
Func readmsg ()->nsdictionary? {
If let buff=self.tcpclient!. ReadAll () {
Let Msgd:nsdata=nsdata (Bytes:buff, Length:buff.count)
Let msgi:nsdictionary= (try!
Nsjsonserialization.jsonobjectwithdata (MSGD,
Options:. mutablecontainers)) as! Nsdictionary
Return Msgi
}
return Nil
}

Loop to receive messages
Func Messageloop () {
While true{
If let msg=self.readmsg () {
Self.processmsg (msg)
}else{
Self.removeme ()
Break
}
}
}

Processing received messages
Func processmsg (msg:nsdictionary) {
If msg["cmd"] as! string== "nickname" {
self.username=msg["nickname"] as! String
}
self.socketserver!. Processusermsg (user:self, msg:msg)
}

Send a message
Func sendmsg (msg:nsdictionary) {
Let Jsondata=try? Nsjsonserialization.datawithjsonobject (MSG, Options:
nsjsonwritingoptions.prettyprinted)
self.tcpclient!. Send (data:jsondata!)
}

Remove the Client
Func Removeme () {
self.socketserver!. Removeuser (self)
}

Close connection
Func Kill () {
self.tcpclient!. Close ()
}
}

(3) Similarly, the client code (VIEWCONTROLLER.SWIFT) here can also be simplified to send and receive data.


Import Uikit

Class Viewcontroller:uiviewcontroller {

Message input Box
@IBOutlet weak var textfiled:uitextfield!
Message output list
@IBOutlet weak var textview:uitextview!

Socket service-Side encapsulation class object
var socketserver:mytcpsocketserver?
Socket client Class object
var socketclient:tcpclient?

Override Func Viewdidload () {
Super.viewdidload ()

Start the server
Socketserver = Mytcpsocketserver ()
Socketserver? Start ()

Initialize the client and connect to the server
Processclientsocket ()
}

Initialize the client and connect to the server
Func Processclientsocket () {
Socketclient=tcpclient (addr: "localhost", port:8080)
Dispatch_async (Dispatch_get_global_queue (dispatch_queue_priority_background, 0), {
()-> Void in

Used to read and parse messages sent from the service side
Func readmsg ()->nsdictionary? {
If let buff=self.socketclient!. ReadAll () {
Let Msgd:nsdata=nsdata (Bytes:buff, Length:buff.count)
Let msgi:nsdictionary =
(try! Nsjsonserialization.jsonobjectwithdata (MSGD,
Options:. mutablecontainers)) as! Nsdictionary
Return Msgi
}
return Nil
}

Connecting to a server
Let (success,msg) =self.socketclient!. Connect (Timeout:5)
If success{
Dispatch_async (Dispatch_get_main_queue (), {
Self.alert ("Connect Success", after: {
})
})

Send user name to server (use randomly generated here)
Let msgtosend=["cmd": "nickname", "nickname": "Visitor \ (Int (Arc4random ()%1000))"]
Self.sendmessage (Msgtosend)

Constantly receiving messages from the server
While true{
If let msg=readmsg () {
Dispatch_async (Dispatch_get_main_queue (), {
Self.processmessage (msg)
})
}else{
Dispatch_async (Dispatch_get_main_queue (), {
Self.disconnect ()
})
Break
}
}
}else{
Dispatch_async (Dispatch_get_main_queue (), {
Self.alert (msg,after: {
})
})
}
})
}

"Send Message" button click
@IBAction func sendmsg (sender:anyobject) {
Let content=textfiled.text!
Let message=["cmd": "MSG", "Content": content]
Self.sendmessage (Message)
Textfiled.text=nil
}

Send a message
Func SendMessage (msgtosend:nsdictionary) {
Let Msgdata=try? Nsjsonserialization.datawithjsonobject (Msgtosend,
Options:. prettyprinted)
self.socketclient!. Send (data:msgdata!)
}

Handling messages returned by the server
Func ProcessMessage (msg:nsdictionary) {
Let cmd:string=msg["cmd"] as! String
Switch (CMD) {
Case "MSG":
Self.textView.text = Self.textView.text +
(msg["from"] as! String) + ":" + (msg["content"] as! String) + "\ n"
Default
Print (msg)
}
}

Pop-up message box
Func Alert (msg:string,after: ()-> (Void)) {
Let Alertcontroller = Uialertcontroller (title: "",
Message:msg,
Preferredstyle:. Alert)
Self.presentviewcontroller (Alertcontroller, Animated:true, Completion:nil)

Dispatch_after (Dispatch_time (Dispatch_time_now, 7), Dispatch_get_main_queue (), {
Alertcontroller.dismissviewcontrolleranimated (False, Completion:nil)
})
}

Override Func didreceivememorywarning () {
Super.didreceivememorywarning ()
}
}

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.