Welcome back friends , In this post i am going to build a simple socket client in C. This project isn’t possible without this beautiful post C Sockets Example. You can learn more about sockets there.
Full code is available in my github repo netchat-cli.
I had to use MultiThreading in this program , because in the example code recieve function is after send function. So if the other client send message to us and we are writing message , then we can only see recieved message after sending the message we have been writing. Thats not how clients like netcat
works , with MultiThreading this problem is solved.
Threads are popular way to improve application through parallelism.
In C , thread library can be included using #include <pthread.h>
.
Creating a thread is really simple. I will use netchat source code as example.
// thread function for listening
void *listen_sock(void *argp);
... inside main()
pthread_t listen_thread;
pthread_create(&listen_thread, NULL, listen_sock, NULL);
...
void *listen_sock(void *argp) {
char reply[2048];
while(1) {
// receive data
if(recv(sock, reply, 2048, 0) < 0) {
"Failed to recieve message \n");
printf(1);
exit(
}"%s", reply);
printf(// reset contents of reply
0, 2048);
memset(reply,
} }
I have declared listen_sock
function with type void*
. This function is executed when thread is created. Then inside main()
declared a variable with type pthread_t
.
pthread_create()
once this function is called , Code inside listen_sock
is executed in the background.
There is also another useful function to handle threads , pthread_join(thread_var, NULL)
. This function block the calling thread and wait till the called thread terminate. Since we need both threads run at same time (main thread and listen_thread) i didn’t used this function.
Edited on 21/02/2022
The above function was straight forward, i didn’t do any security check on that. Today my friend B[]
did code audit on it and shown me a possible vulnerability.
If a malicious user send a string that is not NULL terminated, so reply does not end in NULL character . In that case, printf doesn’t know how long the string is supposed to be and causes a segmentation fault during print
Rewrite of the function :-
// MAX_SIZE is defined at the top and its value is 2048
void *listen_sock(void *argp) {
char reply[MAX_SIZE + 1];
while(1) {
// receive data
size_t r = recv(sock, reply, MAX_SIZE, 0);
if(r <= 0 || r > MAX_SIZE) {
"Failed to recieve message \n");
fprintf(stderr, 1);
exit(else {
} // NULL terminate string ( clear buffer and prevent String Termination Error)
'\0';
reply[r] = "%s", reply);
printf(
}
} }
Final result :-