Sockets

Socket programming is a way of connecting two nodes on a network to communicate with each other.  
We can use a set of socket functions to implement socket in Silk:

listen
For the server side, we can use  _fun("sock_listen", port) to open a port and listen for incoming connection requests from clients.
port is the port number that the socket will listen, the function will return the socket handle if the listening is successful, otherwise the return is null.
The failure is probably that the port is used by other program.

accept
After listening, we can use _fun("sock_accept", sock) to accept an incoming connection.
sock is the socket handle which was returned by listen function.
accept will return a new socket handle referring to the connection, we can use this new socket to receive and send data.

recv
After accepting, we can use _fun("sock_recv", sock, size) to receive the data.
Client side can also use recv to receive the data from the server.
sock is the socket handle which was returned by accept function, size is the size of the data buffer.
The function will return the data it received.

send
we can use _fun("sock_send", sock, data) to send data to client.
Client side can also send data to server.
sock is the socket handle which was returned by accept function, data is the data we need to send.

connect
For the client side, we can use _fun("sock_connect", host, port) to connect to the server and create a connection.
host is the server address, normally it's the IP address or domain, port is the port number that the server is listening.
connect will return a new socket handle referring to the connection. we can use this new socket to receive and send data.

close
Use _fun("sock_close", sock) to close the connection and release the socket.
sock is the socket handle.

shutdown
We can _fun("sock_shutdown", sock, how) to disable sends or receives on a socket.
sock is the socket handle, how is a flag that describes what types of operation will no longer be allowed.
There are 3 options:
  1. how = 0, Shutdown receive operations.
  2. how = 1, Shutdown send operations.
  3. how = 2, Shutdown both send and receive operations.
remoteaddr
Use _fun("sock_remoteaddr", sock) to get the address and port of the client.
sock is the socket handle, the function will return an array which has the IP address and port number.

There is a class CSocket which encapsulates most of the socket functions in Silk installer, it's easy for users to handle socket:
class CSocket()
{
    self.sock=null;

    func listen(port)
    {
        self.sock=_fun("sock_listen",port);
        return self.sock;
    }
    func accept()
    {
        sock= _fun("sock_accept",self.sock);
        client_sock=CSocket();
        client_sock.sock=sock;
        return client_sock;
    }
    func send(data)
    {
        return _fun("sock_send",self.sock,data);
    }
    func recv(size)
    {
        return _fun("sock_recv",self.sock,size);
    }
    func remote_addr()
    {
        return _fun("sock_remoteaddr",self.sock);
    }
    func connect(host,port)
    {
        self.sock=_fun("sock_connect",host,port);
        return self.sock;
    }
    func close()
    {
        _fun("sock_close",self.sock);
     }
     func shutdown(how)
    {
        //how has 3 options (0:shutdown receive, 1:shutdown send, 2:shutdown both)
        _fun("sock_shutdown",self.sock,how);
     }  
     func timeout(seconds)
    {
        _fun("sock_timeout",self.sock,seconds);
     }   
}


The usage of CSocket:
// A simple echo http server

#include "include\socket.si"

func process_client(client)
{
    //get data from client(browser)
    data=client.recv(4096);
    //send data to client
    client.send("HTTP/1.0 200 OK\r\n\r\nHello, this is a simple http server.");
    //close socket
    client.close();
    
    print("sent response to browser");
}

main()
{
    port=80;
    printf("http server is starting to run on port %d\n",port);
    server_sock=CSocket();
    if(!server_sock.listen(port))//listen on a port
    {
        printf("error running on port %d\n",port);
        return;
    }
        
    while(true)
    {
        client_sock= server_sock.accept(); //accept the client request
        _createthread(process_client,client_sock); //process the client request in thread
        
    }
    server_sock.close();
}