Socket Server Example with Swift

12,450

The port number in the socket address must be in big-endian byte order:

server_addr.sin_port = UInt16(4000).bigEndian

So your program actually listens on port 40975 (hex 0xA00F) and not on port 4000 (hex 0x0FA0).

Another problem is here:

var buff_rcv: Array<CChar> = []
// ...
read(client_socket, &buff_rcv, UInt(BUFF_SIZE))

Your buffer is an empty array, but recv() expects a buffer of size BUFF_SIZE. The behaviour is undefined. To get a buffer of the required size, use

var buff_rcv = [CChar](count:BUFF_SIZE, repeatedValue:0)
// ...
read(client_socket, &buff_rcv, UInt(buff_rcv.count))

Remark: Here you cast the address of an Int to the address of an socklen_t and pass that to the accept() function:

client_socket = accept(server_socket, sockaddr_cast(&client_addr), socklen_t_cast(&client_addr_size))

That is not safe. If Int and socklen_t have different sizes then the behaviour will be undefined. You should declare server_addr_size and client_addr_size as socklen_t and remove the socklen_t_cast() function:

client_socket = accept(server_socket, sockaddr_cast(&client_addr), &client_addr_size)
Share:
12,450
Admin
Author by

Admin

Updated on June 05, 2022

Comments

  • Admin
    Admin almost 2 years

    I tried to make an example of simple socket server.

    Build and run successfully. However it doesn't work well.

    Client couldn't connect to this server.

    How to solve this problem? I need your help, thanks.

    import Foundation
    
    let BUFF_SIZE = 1024
    
    func initStruct<S>() -> S {
        let struct_pointer = UnsafePointer<S>.alloc(1)
        let struct_memory = struct_pointer.memory
        struct_pointer.destroy()
        return struct_memory
    }
    
    func sockaddr_cast(p: ConstUnsafePointer<sockaddr_in>) -> UnsafePointer<sockaddr> {
        return UnsafePointer<sockaddr>(p)
    }
    
    func socklen_t_cast(p: UnsafePointer<Int>) -> UnsafePointer<socklen_t> {
        return UnsafePointer<socklen_t>(p)
    }
    
    var server_socket: Int32
    var client_socket: Int32
    var server_addr_size: Int
    var client_addr_size: Int
    
    var server_addr: sockaddr_in = initStruct()
    var client_addr: sockaddr_in = initStruct()
    
    var buff_rcv: Array<CChar> = []
    var buff_snd: String
    
    server_socket = socket(PF_INET, SOCK_STREAM, 0);
    
    if server_socket == -1
    {
        println("[Fail] Create Server Socket")
        exit(1)
    }
    else
    {
        println("[Success] Created Server Socket")
    }
    
    server_addr_size = sizeof(server_addr.dynamicType)
    memset(&server_addr, 0, UInt(server_addr_size));
    
    server_addr.sin_family = sa_family_t(AF_INET)
    server_addr.sin_port = 4000
    server_addr.sin_addr.s_addr = UInt32(0x00000000)    // INADDR_ANY = (u_int32_t)0x00000000 ----- <netinet/in.h>
    
    let bind_server = bind(server_socket, sockaddr_cast(&server_addr), socklen_t(server_addr_size))
    
    if bind_server == -1
    {
        println("[Fail] Bind Port");
        exit(1);
    }
    else
    {
        println("[Success] Binded Port");
    }
    
    if listen(server_socket, 5) == -1
    {
        println("[Fail] Listen");
        exit(1);
    }
    else
    {
        println("[Success] Listening : \(server_addr.sin_port) Port ...");
    }
    
    var n = 0
    
    while n < 1
    {
        client_addr_size = sizeof(client_addr.dynamicType)
        client_socket = accept(server_socket, sockaddr_cast(&client_addr), socklen_t_cast(&client_addr_size))
    
        if client_socket == -1
        {
            println("[Fail] Accept Client Connection");
            exit(1);
        }
        else
        {
            println("[Success] Accepted Client : \(inet_ntoa(client_addr.sin_addr)) : \(client_addr.sin_port)");
        }
    
        read(client_socket, &buff_rcv, UInt(BUFF_SIZE))
    
        println("[Success] Received : \(buff_rcv)")
    
        buff_snd = "\(strlen(buff_rcv)) : \(buff_rcv)"
    
        write(client_socket, &buff_snd, strlen(buff_snd) + 1)
    
        close(client_socket)
    }
    
  • Martin R
    Martin R almost 10 years
    There are actually more problems in your code. For example buff_snd is a Swift String. You cannot simply treat that as a char buffer in write(client_socket, &buff_snd, strlen(buff_snd) + 1).
  • János
    János almost 9 years
    Martin, could you recommend an easy implementation of socket server implemented in Swift that receives and responds strings? socket tutorial below claims, that only 4 method should be implemented, (socket, bind, listen, accept) but all the solution I checked out in SO and github are are so complex, differs from each other and overcomplicated cs.rpi.edu/~moorthy/Courses/os98/Pgms/socket.html
  • Martin R
    Martin R almost 9 years
    @János: Server socket programming isn't easy (at least if you want to handle multiple connections concurrently). GCDAsyncSocket (github.com/robbiehanson/CocoaAsyncSocket) is a nice wrapper written in Objective-C and can be used from Swift, but I do not have any recommendation.