In this post the socket descriptor is created and the options for the socket are set:
// ============================
// Create the socket descriptor
// ============================
let socketDescriptor = socket(
servinfo!.pointee.ai_family, // Use the servinfo created earlier, this makes it IPv4/IPv6 independant
servinfo!.pointee.ai_socktype, // Use the servinfo created earlier, this makes it IPv4/IPv6 independant
servinfo!.pointee.ai_protocol) // Use the servinfo created earlier, this makes it IPv4/IPv6 independant
print("Socket value: \(socketDescriptor)")
// Cop out if there is an error
if socketDescriptor == -1 {
let strError = String(utf8String: strerror(errno)) ?? "Unknown error code"
let message = "Socket creation error \(errno) (\(strError))"
freeaddrinfo(servinfo)
print(message)
return
}
}
// ========================================================================
// Set the socket options (specifically: prevent the "socket in use" error)
// ========================================================================
var optval: Int = 1; // Use 1 to enable the option, 0 to disable
status = setsockopt(
socketDescriptor, // The socket descriptor of the socket on which the option will be set
SOL_SOCKET, // Type of socket options
SO_REUSEADDR, // The socket option id
&optval, // The socket option value
socklen_t(sizeof(Int.self))) // The size of the socket option value
if status == -1 {
let strError = String(utf8String: strerror(errno)) ?? "Unknown error code"
let message = "Setsockopt error \(errno) (\(strError))"
freeaddrinfo(servinfo)
close(socketDescriptor) // Ignore possible errors
print(message)
return
}
This code is pretty straightforward: using the socket call a socket descriptor is created. It takes the information from the servinfo that was created in the previous post. Doing it this way makes it agnostic with respect to IPv4 or IPv6. Possible errors are handled in the same way as before. Except that we now use the strerror call to retrieve the string that describes the error. And of course we have to deallocate the addrinfo structure(s) that were allocated in getaddrinfo. (See previous post)
The next call to setsockopt is not necessary per se, but I like to prevent the infamous "socket in use" error. This error can occur if you start your app, force-quit it and start it again. The first run took control of the socket and since the app did not terminate correctly the OS still thinks that the socket is in use. A second start of the application will thus result in the "socket in use" error.
Using the setsockopt call we can override the standard behaviour and specify that even when the socket is in use, we still want to gain access to it.
The error handling for the setsockopt is as before, but a new twist has been added: since the application at this point has claimed the socket, it must also free the socket when it is no longer needed. Hence the call to close.
Part 3: bind and listen
Check out my Port Spy app in the App Store. A utility that helps you debug your socket based application and includes its own source code. So you can see first hand how to implement socket based io in Swift. And you will be helping this blog!
Did this help?, then please help out a small independent.
If you decide that you want to make a small donation, you can do so by clicking this
link: a cup of coffee ($2) or use the popup on the right hand side for different amounts.
Payments will be processed by PayPal, receiver will be sales at balancingrock dot nl
Bitcoins will be gladly accepted at: 1GacSREBxPy1yskLMc9de2nofNv2SNdwqH
We don't get the world we wish for... we get the world we pay for.
No comments:
Post a Comment