* client / server concept * server concept ** which type of socket? TCP -- one listening socket accept client connections, each of which has its own socket read from and write to the client socket details of client addr/port is in the kernel per client socket UDP -- one listing socket read and write packets to/from the one socket must get addr/port info from the kernel per packet and track yourself ** difference between an API server and communication server *** API server, request processing is generally independent need protection around concurrent access to data *** communication server, hub for group communcation generally easier if all fds are available in the same process and then use poll / select to manage all of the incomming comms * poll / select ** used to block on multiple sources of input / output at the same time tell the kernel the list of fds you're interested in for read and/or write the kernel blocks until one or more fds is ready for that operation when poll returns, you _know_ which fds are ready ** select a bit simpler to use, but doesn't scale well large numbers of active fds make it inefficient fd_set read_fds; FD_ZERO(&read_fds); FD_SET(STDIN_FILENO, &read_fds); select((STDIN_FILENO+1), &read_fds, NULL, NULL, NULL); FD_ISSET(STDIN_FILENO, &read_fds); ** poll a little bit more complicated data structure, but scales much better only as many elements in the data structure as fds of interest struct pollfd fds[1]; fds[0].fd = STDIN_FILENO; fds[0].events = POLLIN; fds[0].revents = 0; poll(fds, 1, -1); (fds[0].revents & POLLIN) ** control loop for poll while true: determine the number of fds build your struct pollfd array call poll handle poll * ideas around how to handle the JOIN timeout ** set a timer, on JOIN response cancel the timer, if the timer triggers, handle timeout ** use the poll/select timeout to block until it's time to give up what if the user is doing things in the curses window? * use pthreads? ** part of the same process but with a separate execution flow shared memory space and shared fate ** you can use standard IPC mechanisms, but you can also just use memory ** for pthreads, there are analgous operations to those with processes fork/exec -> pthread_create wait -> pthread_join safety -> pthread_mutex signals -> pthread_cond * nested ifs / call trees * parent cmd -> child cmd -> child cmd -> child cmd -> child cmd -> child cmd -> child cmd struct cmd { the actual command to execute pointer to child command list pointer to next command };