- Saved searches
- Use saved searches to filter your results more quickly
- License
- elhayra/tcp_server_client
- Name already in use
- Sign In Required
- Launching GitHub Desktop
- Launching GitHub Desktop
- Launching Xcode
- Launching Visual Studio Code
- Latest commit
- Git stats
- Files
- README.md
- About
- Programming UDP sockets in C on Linux – Client and Server example
- Simple UDP Server
- UDP Client
- Conclusion
- 16 Comments
Saved searches
Use saved searches to filter your results more quickly
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.
A thin and simple C++ TCP client server
License
elhayra/tcp_server_client
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Sign In Required
Please sign in to use Codespaces.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching Xcode
If nothing happens, download Xcode and try again.
Launching Visual Studio Code
Your codespace will open once ready.
There was a problem preparing your codespace, please try again.
Latest commit
Git stats
Files
Failed to load latest commit information.
README.md
A thin and simple C++ TCP client and server library with examples.
Currently, both linux and mac are supported
Simple tcp server-client examples. They are optimized for simplicity and ease of use/read but not for performance. However, I believe tuning this code to suite your needs should be easy in most cases. You can find code examples of both server and client under the ‘examples’ directory. Both the library and the examples are well documented.
The server is thread-safe, and can handle multiple clients at the same time, and remove dead clients resources automatically.
build the examples and static library file:
$ cd tcp_server_client $ ./build
run the server and client examples: Navigate into the build folder and run in the terminal:
This project is set to use CMake to build both the client example and the server example. In addition, CMake builds a static library file to hold the common code to both server and client.
In order to build the project you can either use the build.sh script:
$ cd tcp_server_client $ ./build
$ cd tcp_server_client $ mkdir build $ cmake .. $ make
The build process generate three files: libtcp_client_server.a , tcp_client and tcp_server . The last two are the executables of the examples which can be executed in the terminal.
Building Only Server or Client
By default, the CMake configuration builds both server and client. However, you can use flags to build only one of the apps as follows:
Disabling the server build
To build only the client, disable the server build by replace the cmake .. call by:
And then run the make command as usual.
Disabling the client build
To build only the server, disable the client build by replace the cmake .. call by:
And then run the make command as usual.
Navigate into the build folder and run in the terminal:
You should see a menu output on the screen, we’ll get back to that. In a different terminal, run the client:
You should see a similar menu for the client too. In addition, as mentioned, the client will try to connect to the server right away, so you should also see an output messages on both client and server terminals indicating that the connection succeeded. Now, feel free to play with each of the client/server menus. You can exchange messages b/w client and server, print active clients etc. You can also spawn more clients in other terminals to see how the server handles multiple clients.
After playing with the examples, go into the examples source code and have a look at the main() function to learn how the server and client interacts. The examples are heavily documented. In addition, you can also look at the public functions in tcp_client.h and tcp_server.h to learn what APIs are available.
Both server and client are using the observer design pattern to register and handle events. When registering to an event with a callback, you should make sure that:
- The callback is fast (not doing any heavy lifting tasks) because those callbacks are called from the context of the server or client.
- No server / client function calls are made in those callbacks to avoid possible deadlock.
About
A thin and simple C++ TCP client server
Programming UDP sockets in C on Linux – Client and Server example
This article describes how to write a simple echo server and client using udp sockets in C on Linux/Unix platform.
UDP sockets or Datagram sockets are different from the TCP sockets in a number of ways.
The most important difference is that UDP sockets are not connection oriented. More technically speaking, a UDP server does not accept connections and a udp client does not connect to server.
The server will bind and then directly receive data and the client shall directly send the data.
Simple UDP Server
So lets first make a very simple ECHO server with UDP socket. The flow of the code would be
socket() -> bind() -> recvfrom() -> sendto()
/* Simple udp server */ #include //printf #include //memset #include //exit(0); #include #include #define BUFLEN 512 //Max length of buffer #define PORT 8888 //The port on which to listen for incoming data void die(char *s) < perror(s); exit(1); >int main(void) < struct sockaddr_in si_me, si_other; int s, i, slen = sizeof(si_other) , recv_len; char buf[BUFLEN]; //create a UDP socket if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) < die("socket"); >// zero out the structure memset((char *) &si_me, 0, sizeof(si_me)); si_me.sin_family = AF_INET; si_me.sin_port = htons(PORT); si_me.sin_addr.s_addr = htonl(INADDR_ANY); //bind socket to port if( bind(s , (struct sockaddr*)&si_me, sizeof(si_me) ) == -1) < die("bind"); >//keep listening for data while(1) < printf("Waiting for data. "); fflush(stdout); //try to receive some data, this is a blocking call if ((recv_len = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen)) == -1) < die("recvfrom()"); >//print details of the client/peer and the data received printf("Received packet from %s:%d\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port)); printf("Data: %s\n" , buf); //now reply the client with the same data if (sendto(s, buf, recv_len, 0, (struct sockaddr*) &si_other, slen) == -1) < die("sendto()"); >> close(s); return 0; >
Run the above code by doing a gcc server.c && ./a.out at the terminal. Then it will show waiting for data like this
$ gcc server.c && ./a.out Waiting for data.
Next step would be to connect to this server using a client. We shall be making a client program a little later but first for testing this code we can use netcat.
Test the server with netcat
Open another terminal and connect to this udp server using netcat and then send some data. The same data will be send back by the server. Over here we are using the ncat command from the nmap package.
$ ncat -vv localhost 8888 -u Ncat: Version 5.21 ( http://nmap.org/ncat ) Ncat: Connected to 127.0.0.1:8888. hello hello world world
Note : We had to use netcat because the ordinary telnet command does not support udp protocol. The -u option of netcat specifies udp protocol.
Check open port with netstat
The netstat command can be used to check if the udp port is open or not.
$ netstat -u -a Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State udp 0 0 localhost:11211 *:* udp 0 0 localhost:domain *:* udp 0 0 localhost:45286 localhost:8888 ESTABLISHED udp 0 0 *:33320 *:* udp 0 0 *:ipp *:* udp 0 0 *:8888 *:* udp 0 0 *:17500 *:* udp 0 0 *:mdns *:* udp 0 0 localhost:54747 localhost:54747 ESTABLISHED udp6 0 0 [::]:60439 [::]:* udp6 0 0 [::]:mdns [::]:*
Note the *:8888 entry of output. Thats our server program.
The entry that has localhost:8888 in «Foreign Address» column, indicates some client connected to it, which is netcat over here.
UDP Client
Now that we have tested our server with netcat, its time to make a client and use it instead of netcat.
The program flow is like
/* Simple udp client */ #include //printf #include //memset #include //exit(0); #include #include #define SERVER "127.0.0.1" #define BUFLEN 512 //Max length of buffer #define PORT 8888 //The port on which to send data void die(char *s) < perror(s); exit(1); >int main(void) < struct sockaddr_in si_other; int s, i, slen=sizeof(si_other); char buf[BUFLEN]; char message[BUFLEN]; if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) < die("socket"); >memset((char *) &si_other, 0, sizeof(si_other)); si_other.sin_family = AF_INET; si_other.sin_port = htons(PORT); if (inet_aton(SERVER , &si_other.sin_addr) == 0) < fprintf(stderr, "inet_aton() failed\n"); exit(1); >while(1) < printf("Enter message : "); gets(message); //send the message if (sendto(s, message, strlen(message) , 0 , (struct sockaddr *) &si_other, slen)==-1) < die("sendto()"); >//receive a reply and print it //clear the buffer by filling null, it might have previously received data memset(buf,'/* Simple udp client */ #include //printf #include //memset #include //exit(0); #include #include #define SERVER "127.0.0.1" #define BUFLEN 512 //Max length of buffer #define PORT 8888 //The port on which to send data void die(char *s) < perror(s); exit(1); >int main(void) < struct sockaddr_in si_other; int s, i, slen=sizeof(si_other); char buf[BUFLEN]; char message[BUFLEN]; if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) < die("socket"); >memset((char *) &si_other, 0, sizeof(si_other)); si_other.sin_family = AF_INET; si_other.sin_port = htons(PORT); if (inet_aton(SERVER , &si_other.sin_addr) == 0) < fprintf(stderr, "inet_aton() failed\n"); exit(1); >while(1) < printf("Enter message : "); gets(message); //send the message if (sendto(s, message, strlen(message) , 0 , (struct sockaddr *) &si_other, slen)==-1) < die("sendto()"); >//receive a reply and print it //clear the buffer by filling null, it might have previously received data memset(buf,'\0', BUFLEN); //try to receive some data, this is a blocking call if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == -1) < die("recvfrom()"); >puts(buf); > close(s); return 0; >', BUFLEN); //try to receive some data, this is a blocking call if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == -1) < die("recvfrom()"); >puts(buf); > close(s); return 0; >
Run the above program and it will ask for some message
$ gcc client.c -o client && ./client Enter message : happy happyWhatever message the client sends to server, the same comes back as it is and is echoed.
Conclusion
UDP sockets are used by protocols like DNS etc. The main idea behind using UDP is to transfer small amounts of data and where reliability is not a very important issue. UDP is also used in broadcasting/multicasting.
When a file transfer is being done or large amount of data is being transferred in parts the transfer has to be much more reliable for the task to complete. Then the TCP sockets are used.
A Tech Enthusiast, Blogger, Linux Fan and a Software Developer. Writes about Computer hardware, Linux and Open Source software and coding in Python, Php and Javascript. He can be reached at [email protected] .
16 Comments
- Joe June 7, 2021 at 3:03 pm Hello. You seem to have double pasted the second code sample inside itself. THanks for the tutorial
- Silver Moon Post author August 14, 2018 at 4:04 pm i haven’t done sockets for a long time. right now i can think of using multiple threads do things in parallel.
so the main thread could do its background work, and an extra thread could listen to the udp port for incoming messages.
or the other way round.
but i am not sure if that is the best approach. there might be better alternatives.
- Bryan Kelly March 15, 2018 at 4:04 am And ncat used option -vv which on my Ubuntu system means verbose. The captured text does not have the verbose output. My system had five lines of information for each line of typed in data.
Still, I am new to Linux and Ubuntu and this is an unexpected cool way to test the server app.
Thank you.