CSE-111 Client/Server and Sockets
Client/Server and Sockets
Hello, dear friend, you can consult us at any time if you have any questions, add WeChat: THEend8_
CSE-111 Client/Server and Sockets
2. Programs
In this project, two main programs are to be written for the three parts of the
project : the daemon and server, and the client. There will also be several library
files written to be used by the programs. The general function is similar to sftp(1).
cixd
Usage : cixd port
Creates a server socket and goes into an infinite loop : When it accepts a client
socket, it uses fork(2) to create a child process, which functions as the server
to communicate with the client. The daemon listens for connections on the
given port.
The server is forked with an open socket communicating with the client. Its
loop repeatedly reads commands and information from the client and acts on
those commands, returning information back to the client. Its loop will be a
receive followed by a send, responding to client requests. It exits when the
client closes the socket. It does no terminal I/O except for debugging purposes.
cix
Usage : cix host port
The client interacts with the user. Commands are read from the terminal (or
redirect), each of which is executed one at a time by communicating with the
server. Results are then displayed at the terminal. The client connects to the
given host and port.
3. Interactive Commands
The cix client responds to commands read from the standard output and writes output
to the standard output and error and accesses files. In the syntax below,
Courier Bold are literal characters actually typed in, while Roman Italic stands for
appropriate substitutions.
CSE-111 • Winter 2020 • Program 4 • Client/Server and Sockets 2 of 5
exit
Quit the program. An end of file marker or Control/D is equivalent.
get filename
Copy the file named filename on the remote server and create or overwrite a
file of the same name in the current directory.
help
A summary of available commands is printed.
ls
Causes the remote server to execute the command ls -l and prints the output
to the user’s terminal.
put filename
Copies a local file into the socket and causes the remote server to create that
file in its directory.
rm filename
Causes the remote server to remove the file.
4. Protocol used by the cix* programs
For the client and server to communicate,aprotocol needs to be established. Each
message must be framed in terms of a header and a payload. The header always
consists of a struct of size 64 bytes. All messages between client and server consist
of these 64 bytes, possibly followed by a payload. For alignment purposes, the
nbytes field is first. Before filling in the fields, use memset(3) to clear the struct.
enum class cix_command : uint8_t {
ERROR = 0, EXIT, GET, HELP, LS, PUT, RM, FILEOUT, LSOUT, ACK, NAK
};
size_t constexpr FILENAME_SIZE = 59;
struct cix_header {
uint32_t nbytes {0};
cix_command command {cix_command::ERROR};
char filename[FILENAME_SIZE] {};
};
The purposes of the fields are as follows :
uint32_t nbytes;
The number of bytes in the payload if there is any payload. Otherwise it must
be zero (MBZ). This field is sent in network byte order and so must use the
functions ntohl(3) and htonl(3) when loading and storing data.
cix_command command;
A single byte containing one of the cix_command constants. Note that the enum
is specifically a uint8_t single byte type.
char filename[59];
The name of the file being transferred or removed. The filename may not have
any slash (’/’) characters in it and must be null-terminated (with ’\0’). All
bytes following the null must also be null. Pathnames with slashes and filenames
longer than 58 characters are prohibited.
CSE-111 • Winter 2020 • Program 4 • Client/Server and Sockets 3 of 5
Following are the meanings of each of the cix_command values. Each is either client
to server (C→S) or server to client (S→C), but never both.
cix_command::ERROR
An error flag to indicate an invalid header. Used internally.
cix_command::EXIT
Internal to cix, not used in communication.
cix_command::GET (C→S)
Request a file from the server. The filename is used both remotely and locally.
The payload length is 0.
cix_command::HELP
Internal to cix, not used in communication.
cix_command::LS (C→S)
Request file (ls) information. The payload length and filename are zeroed.
cix_command::PUT (C→S)
The length of the payload is the number of bytes in the file. The contents of
the file immediately follow the header. The bytes of the payload are unstructured
and may contain null bytes. Binary files are acceptable.
cix_command::RM (C→S)
Request to remove a file. The payload length is 0.
cix_command::FILEOUT (S→C)
Response to a cix_command::GET. The filename is the same as in the request
and the payload length reflects the number of bytes in the file. The payload
consists of the bytes of the file.
cix_command::LSOUT (S→C)
Response to a cix_command::LS. The filename is zeroed and the payload length
is the number of bytes sent in the payload. The payload is the output of the
command ls -l.
cix_command::ACK (S→C)
Response to either a cix_command::PUT or a cix_command::RM indicating that the
request was successfully completed.
cix_command::NAK (S→C)
Response to any request that fails. There is no payload. The filename field is
the same as was in the original request. The nbytes field is set to the value of
errno in the server’s attempt to preform a task.
5. Procedures
Each of the above commands requires procedures for accessing files, including reading
files from disk and writing files to disk, as well as accessing directories. When
any of the system calls fails in the server, the server immediately terminates the
operation and sends the value of errno back to the client in a cix_command::NAK message.
CSE-111 • Winter 2020 • Program 4 • Client/Server and Sockets 4 of 5
(a) For the client or server to send a file it must first be read into a buffer. Binary
files must be properly handled, so protocols which assume text files won’t
work. To load a file from disk, use ifstream::read(), collecting characters into
a buffer. Read the entire file into a buffer then close it. After that, it may be
sent down the socket.
(b) Alternatively, stat(2) the file to see how large it is, and send the file down the
socket piecemeal. In conjunction with stat(2), it is also possible to may the file
into memory using mmap(2), provided that the memory thus acquired is
released with munmap(2) when the file operation is complete.
(c) When receiving a file from the socket, Receive the header and determine the
size of the file. Create an ofstream and use ofstream::write() to write the
parts of the file as they are received from the socket. A C++ stream is closed
when the variable goes out of scope, or you can call close.
(d) To delete a file for the cix_command::RM command, use unlink(2) :
rc = unlink (filename);
(e) To execute the cix_command::LS command use popen(2) and pclose(2) to create
a pipe stream from the ls(1) command
FILE* pipe = popen (“ls -l”, “r”);
Then read the characters from the pipe in the easiest way, probably by using
fgets(3). Finally, pclose(pipe). Then send the output back the client in a cix_
command::LSOUT message.
6. Modules
There will need to be several modules in this suite of programs. Each of the programs,
of course, will have its own source file with a main function in it.
The sockets module will be a useful inclusion into the program as its own module.
There should also be a cix_protocol module to implement the protocols and contain
code for accessing files and sockets, since these will be used by both the client and
the server.