I am trying to program a simple server socket. It is successful to connect to client. But after I disconnect, and try to re-establish the server socket, during binding I got an error (errno = 48, EADDRINUSE). Anyone know how to fix it?
func initServerSocket(serverSocket: Int32) -> Int32 {
var clientSocket: Int32 = -1
var server_addr_size: Int
var client_addr_size = socklen_t(MemoryLayout<sockaddr_in>.size)
var server_addr = sockaddr_in()
var client_addr = sockaddr_in()
server_addr_size = MemoryLayout<sockaddr_in>.size
memset(&server_addr, 0, server_addr_size);
server_addr.sin_family = sa_family_t(AF_INET)
server_addr.sin_port = UInt16(8080).bigEndian
server_addr.sin_addr.s_addr = UInt32(0x00000000)
let bind_server = withUnsafePointer(to: &server_addr) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
bind(serverSocket, $0, socklen_t(MemoryLayout<sockaddr_in>.stride))
}
}
if bind_server == -1 {
print("[Fail] Bind Port, Error: \(errno)");
exit(1);
} else {
print("[Success] Binded Port \(bind_server)");
}
if listen(serverSocket, 5) == -1 {
print("[Fail] Listen");
exit(1);
} else {
print("[Success] Listening : \(server_addr.sin_port) Port ...");
}
clientSocket = withUnsafeMutablePointer(to: &client_addr) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
accept(serverSocket, $0, &client_addr_size)
}
}
if clientSocket == -1 {
print("[Fail] Accept Client Connection \(errno)");
exit(1);
} else {
print("[Success] Accepted Client : \(inet_ntoa(client_addr.sin_addr)!) : \(client_addr.sin_port)!");
}
return clientSocket
}
Disconnect function:
func disconnect() {
if clientSocket != -1 {
self.inputStream.close()
self.outputStream.close()
if close(HiveConfig.clientSocket) == -1 {
print("serverSocket close error")
}
if close(HiveConfig.serverSocket) == -1 {
print("serverSocket close error")
}
}
}
I figure out that on my code before bind need to add the following code to make the address reused.
var opt:Int = 1
setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, &opt, socklen_t(MemoryLayout.size(ofValue: opt)));
Related
For a local server I need to specify a port, which must not be in use. There's a really neat solution in Python to get a free port. However, such a socket library is not available in Swift. So I tried Using BSD Sockets in Swift, but that actually wants a port to be specified upfront and I cannot get the bind command to work. Here's the code I tried:
let socketFD = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if socketFD == -1 {
print("Error creating BSD Socket")
return
}
var hints = addrinfo(
ai_flags: AI_PASSIVE, // Assign the address of the local host to the socket structures
ai_family: AF_UNSPEC, // Either IPv4 or IPv6
ai_socktype: SOCK_STREAM, // TCP
ai_protocol: 0,
ai_addrlen: 0,
ai_canonname: nil,
ai_addr: nil,
ai_next: nil)
var servinfo: UnsafeMutablePointer<addrinfo>? = nil
let addrInfoResult = getaddrinfo(
nil, // Any interface
"8000", // The port on which will be listenend
&hints, // Protocol configuration as per above
&servinfo);
if addrInfoResult != 0 {
print("Error getting address info: \(errno)")
return
}
let bindResult = Darwin.bind(socketFD, servinfo!.pointee.ai_addr, socklen_t(servinfo!.pointee.ai_addrlen));
if bindResult == -1 {
print("Error binding socket to Address: \(errno)")
return
}
let listenResult = Darwin.listen(socketFD, 1);
if listenResult == -1 {
print("Error setting our socket to listen")
return
}
let port = Darwin.getsockname(socketFD, nil, nil);
The bind call always returns -1 and since I want to get a free port it makes no sense to specify one in getaddrinfo. What's the correct way here?
Here's a working solution:
func findFreePort() -> UInt16 {
var port: UInt16 = 8000;
let socketFD = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if socketFD == -1 {
//print("Error creating socket: \(errno)")
return port;
}
var hints = addrinfo(
ai_flags: AI_PASSIVE,
ai_family: AF_INET,
ai_socktype: SOCK_STREAM,
ai_protocol: 0,
ai_addrlen: 0,
ai_canonname: nil,
ai_addr: nil,
ai_next: nil
);
var addressInfo: UnsafeMutablePointer<addrinfo>? = nil;
var result = getaddrinfo(nil, "0", &hints, &addressInfo);
if result != 0 {
//print("Error getting address info: \(errno)")
close(socketFD);
return port;
}
result = Darwin.bind(socketFD, addressInfo!.pointee.ai_addr, socklen_t(addressInfo!.pointee.ai_addrlen));
if result == -1 {
//print("Error binding socket to an address: \(errno)")
close(socketFD);
return port;
}
result = Darwin.listen(socketFD, 1);
if result == -1 {
//print("Error setting socket to listen: \(errno)")
close(socketFD);
return port;
}
var addr_in = sockaddr_in();
addr_in.sin_len = UInt8(MemoryLayout.size(ofValue: addr_in));
addr_in.sin_family = sa_family_t(AF_INET);
var len = socklen_t(addr_in.sin_len);
result = withUnsafeMutablePointer(to: &addr_in, {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
return Darwin.getsockname(socketFD, $0, &len);
}
});
if result == 0 {
port = addr_in.sin_port;
}
Darwin.shutdown(socketFD, SHUT_RDWR);
close(socketFD);
return port;
}
I’m sure someone can solve this in seconds but I’m very new to swift, using playgrounds on the iPad. I’m trying to modify some SendUDP code to recieve instead, but I can’t solve the compile error (unsafepointer is not convertible to unsaferawbufferpointer) on the readResult= line. The SEND works fine with very similar code, but I’m really struggling here, way out of my depth...
Here’s the code
func readUDP() {
guard
let addresses =
try ? addressesFor(host: "192.168.4.1", port: 80)
else {
print("host not found")
return
}
if addresses.count != 1 {
print("host ambiguous; using the first one")
}
address = addresses[0]
fd1 = socket(Int32(address.ss_family), SOCK_DGRAM, 0)
guard fd1 >= 0
else {
print("`socket` failed`")
return
}
defer {
let junk = close(fd1)
assert(junk == 0)
}
var message = [UInt8](repeating: 0, count: 1024)
let messageCount = message.count
var readResult = message.withUnsafeBytes {
(messagePtr: UnsafePointer < UInt8 > ) - > Int in
return address.withSockAddr {
(sa, saLen) - > Int in
return recvfrom(fd1, messagePtr, messageCount, 0, sa, & saLen)
}
}
guard readResult >= 0
else {
print("read failed")
return
}
print("success")
}
You can use Swift's implicit bridging to simplify to something like this:
var message = [UInt8](repeating: 0, count: 1024)
let messageCount = message.count
var readResult = address.withSockAddr {
(sa, saLen) - > Int in
return recvfrom(fd1, &message, messageCount, 0, sa, &saLen)
}
guard readResult >= 0
else {
print("read failed")
return
}
I try to establish a connection to a TCP server, unfortunately without success. Here is my actual way. Does anyone knows, where the error is? I'm getting the error at CFSocketConnectToAddress (I get the .error result, so my code results in the error while connecting print).
Any ideas?
host = "192.168.0.20"
port = 8888
socket = CFSocketCreate(kCFAllocatorDefault,
AF_INET,
SOCK_STREAM,
IPPROTO_TCP,
CFSocketCallBackType.readCallBack.rawValue, { (socket: CFSocket?, callBackType: CFSocketCallBackType, address: CFData?, data: UnsafeRawPointer?, info: UnsafeMutableRawPointer?) -> Void in print("callback test") }, nil)
if socket == nil {
print("Error while creating socket")
} else {
var sin = sockaddr_in(
sin_len: UInt8(MemoryLayout<sockaddr_in>.size),
sin_family: sa_family_t(AF_INET),
sin_port: in_port_t(port),
sin_addr: in_addr(s_addr: inet_addr(host)),
sin_zero: (0,0,0,0,0,0,0,0)
)
addressData = NSData(bytes: &sin, length: MemoryLayout.size(ofValue: sin)) as CFData
let connectResult: CFSocketError = CFSocketConnectToAddress(socket, addressData!, 10)
switch connectResult {
case .success:
print("Connected")
case .error:
print("Error while connecting")
case .timeout:
print("Timeout while connecting")
}
The problem was the port! The htons macro is not available in swift. This is the working way now:
func connectToServer(timeout: Int=10) throws {
// check, if address is valid https://linux.die.net/man/3/inet_makeaddr
let inAddr = inet_addr(host)
if inAddr == INADDR_NONE {
throw SocketError.noValidAddress
}
let socket = CFSocketCreate(kCFAllocatorDefault,
AF_INET,
SOCK_STREAM,
IPPROTO_TCP,
CFSocketCallBackType.readCallBack.rawValue,
{ (socket, callBackType, address, data, info) in
TCPClientCallBack(socket: socket, callBackType: callBackType, address: address, data: data, info: info)
},
nil)
if socket == nil {
throw SocketError.socketCreationFailed
}
var sin = sockaddr_in() // https://linux.die.net/man/7/ip
sin.sin_len = __uint8_t(MemoryLayout.size(ofValue: sin))
sin.sin_family = sa_family_t(AF_INET)
sin.sin_port = UInt16(port).bigEndian
sin.sin_addr.s_addr = inAddr
let addressDataCF = NSData(bytes: &sin, length: MemoryLayout.size(ofValue: sin)) as CFData
let socketErr = CFSocketConnectToAddress(socket, addressDataCF, CFTimeInterval(timeout))
switch socketErr {
case .success:
print("connected")
case .error:
throw SocketError.connectionError
case .timeout:
throw SocketError.connectionTimeout
}
}
enum SocketError: Error {
case noValidAddress
case socketCreationFailed
case connectionError
case connectionTimeout
}
Any one help me to get Network IP (i.e 103.62.238.190) in Swift 3
I tried below code for it, but this function get System Ip.
I tried so many time to find the solution but still i didn't get any exact function for it.
func getIFAddresses() -> [String] {
var addresses = [String]()
// Get list of all interfaces on the local machine:
var ifaddr : UnsafeMutablePointer<ifaddrs>?
guard getifaddrs(&ifaddr) == 0 else { return [] }
guard let firstAddr = ifaddr else { return [] }
// For each interface ...
for ptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
let flags = Int32(ptr.pointee.ifa_flags)
var addr = ptr.pointee.ifa_addr.pointee
// Check for running IPv4, IPv6 interfaces. Skip the loopback interface.
if (flags & (IFF_UP|IFF_RUNNING|IFF_LOOPBACK)) == (IFF_UP|IFF_RUNNING) {
if addr.sa_family == UInt8(AF_INET) || addr.sa_family == UInt8(AF_INET6) {
// Convert interface address to a human readable string:
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
if (getnameinfo(&addr, socklen_t(addr.sa_len), &hostname, socklen_t(hostname.count),
nil, socklen_t(0), NI_NUMERICHOST) == 0) {
let address = String(cString: hostname)
addresses.append(address)
}
}
}
}
freeifaddrs(ifaddr)
return addresses
}
I am using the following code to get the network adapters of my macOS System:
private func getAdapters() -> [Adapter]
{
var adapters: [Adapter] = []
var addresses: UnsafeMutablePointer<ifaddrs>?
guard getifaddrs(&addresses) == 0 else { return adapters }
guard let firstAddr = addresses else { return adapters }
for ptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next })
{
let address = ptr.pointee
let rawData = address.ifa_data
let name = address.ifa_name
let socket: sockaddr = address.ifa_addr.pointee
// Set up some filters
let loopback = (address.ifa_flags & UInt32(IFF_LOOPBACK)) != 0
let up = (address.ifa_flags & UInt32(IFF_UP)) != 0
let p2p = (address.ifa_flags & UInt32(IFF_POINTOPOINT)) != 0
if rawData != nil && name != nil && socket.sa_family == UInt8(AF_LINK) && !loopback && up && !p2p
{
let adapterName = String(utf8String: UnsafePointer<CChar>(name!))
let adapter = Adapter(name: adapterName!)
adapters.append(adapter)
}
}
freeifaddrs(addresses)
return adapters
}
Now I am looking for a way to figure out, which of those adapters is the "active" one, i.e. which one is connected to the internet.
I want to get the adapter that has the "green dot" in the network settings. How can I get this information?
Regards,
Sascha