Skip to content

Commit 690d490

Browse files
NVombatPanquesito7github-actions
authored
TCP Full Duplex Server Client Communication (#856)
* TCP Full Duplex Server Client Communication * Changes made to successfully complete 5th Check * Update client_server/tcp_full_duplex_server.c Co-authored-by: David Leal <[email protected]> * updating DIRECTORY.md * Update tcp_full_duplex_client.c * Update client_server/tcp_full_duplex_client.c Co-authored-by: David Leal <[email protected]> Co-authored-by: David Leal <[email protected]> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
1 parent 16d115d commit 690d490

File tree

3 files changed

+370
-0
lines changed

3 files changed

+370
-0
lines changed

DIRECTORY.md

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
## Client Server
44
* [Client](https://github.com/TheAlgorithms/C/blob/master/client_server/client.c)
55
* [Server](https://github.com/TheAlgorithms/C/blob/master/client_server/server.c)
6+
* [Tcp Full Duplex Client](https://github.com/TheAlgorithms/C/blob/master/client_server/tcp_full_duplex_client.c)
7+
* [Tcp Full Duplex Server](https://github.com/TheAlgorithms/C/blob/master/client_server/tcp_full_duplex_server.c)
68
* [Tcp Half Duplex Client](https://github.com/TheAlgorithms/C/blob/master/client_server/tcp_half_duplex_client.c)
79
* [Tcp Half Duplex Server](https://github.com/TheAlgorithms/C/blob/master/client_server/tcp_half_duplex_server.c)
810
* [Udp Client](https://github.com/TheAlgorithms/C/blob/master/client_server/udp_client.c)
+173
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/**
2+
* @file
3+
* @author [NVombat](https://github.com/NVombat)
4+
* @brief Client-side implementation of [TCP Full Duplex
5+
* Communication](http://www.tcpipguide.com/free/t_SimplexFullDuplexandHalfDuplexOperation.htm)
6+
* @see tcp_full_duplex_server.c
7+
*
8+
* @details
9+
* The algorithm is based on the simple TCP client and server model. However,
10+
* instead of the server only sending and the client only receiving data,
11+
* The server and client can both send and receive data simultaneously. This is
12+
* implemented by using the `fork` function call so that in the server the child
13+
* process can recieve data and parent process can send data, and in the client
14+
* the child process can send data and the parent process can receive data. It
15+
* runs an infinite loop and can send and receive messages indefinitely until
16+
* the user exits the loop. In this way, the Full Duplex Form of communication
17+
* can be represented using the TCP server-client model & socket programming
18+
*/
19+
20+
#include <arpa/inet.h> /// For the type in_addr_t and in_port_t
21+
#include <netdb.h> /// For structures returned by the network database library - formatted internet addresses and port numbers
22+
#include <netinet/in.h> /// For in_addr and sockaddr_in structures
23+
#include <stdint.h> /// For specific bit size values of variables
24+
#include <stdio.h> /// Variable types, several macros, and various functions for performing input and output
25+
#include <stdlib.h> /// Variable types, several macros, and various functions for performing general functions
26+
#include <string.h> /// Various functions for manipulating arrays of characters
27+
#include <sys/socket.h> /// For macro definitions related to the creation of sockets
28+
#include <sys/types.h> /// For definitions to allow for the porting of BSD programs
29+
#include <unistd.h> /// For miscellaneous symbolic constants and types, and miscellaneous functions
30+
31+
#define PORT 10000 /// Define port over which communication will take place
32+
33+
/**
34+
* @brief Utility function used to print an error message to `stderr`.
35+
* It prints `str` and an implementation-defined error
36+
* message corresponding to the global variable `errno`.
37+
* @returns void
38+
*/
39+
void error()
40+
{
41+
perror("Socket Creation Failed");
42+
exit(EXIT_FAILURE);
43+
}
44+
45+
/**
46+
* @brief Main function
47+
* @returns 0 on exit
48+
*/
49+
int main()
50+
{
51+
/** Variable Declarations */
52+
uint32_t
53+
sockfd; ///< socket descriptors - Like file handles but for sockets
54+
char sendbuff[1024],
55+
recvbuff[1024]; ///< character arrays to read and store string data
56+
/// for communication
57+
58+
struct sockaddr_in
59+
server_addr; ///< asic structures for all syscalls and functions that
60+
/// deal with internet addresses. Structures for handling
61+
/// internet addresses
62+
63+
/**
64+
* The TCP socket is created using the socket function.
65+
*
66+
* AF_INET (Family) - it is an address family that is used to designate the
67+
* type of addresses that your socket can communicate with
68+
*
69+
* SOCK_STREAM (Type) - Indicates TCP Connection - A stream socket provides
70+
* for the bidirectional, reliable, sequenced, and unduplicated flow of data
71+
* without record boundaries. Aside from the bidirectionality of data flow,
72+
* a pair of connected stream sockets provides an interface nearly identical
73+
* to pipes.
74+
*
75+
* 0 (Protocol) - Specifies a particular protocol to be used with the
76+
* socket. Specifying a protocol of 0 causes socket() to use an unspecified
77+
* default protocol appropriate for the requested socket type.
78+
*/
79+
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
80+
{
81+
error();
82+
}
83+
84+
/**
85+
* Server Address Information
86+
*
87+
* The bzero() function erases the data in the n bytes of the memory
88+
* starting at the location pointed to, by writing zeros (bytes
89+
* containing '\0') to that area.
90+
*
91+
* We bind the server_addr to the internet address and port number thus
92+
* giving our socket an identity with an address and port where it can
93+
* listen for connections
94+
*
95+
* htons - The htons() function translates a short integer from host byte
96+
* order to network byte order
97+
*
98+
* htonl - The htonl() function translates a long integer from host byte
99+
* order to network byte order
100+
*
101+
* These functions are necessary so that the binding of address and port
102+
* takes place with data in the correct format
103+
*/
104+
bzero(&server_addr, sizeof(server_addr));
105+
server_addr.sin_family = AF_INET;
106+
server_addr.sin_port = htons(PORT);
107+
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
108+
109+
printf("Client is running...\n");
110+
111+
/**
112+
* Connects the client to the server address using the socket descriptor
113+
* This enables the two to communicate and exchange data
114+
*/
115+
connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
116+
117+
printf("Client is connected...\n");
118+
119+
/**
120+
* Communication between client and server
121+
*
122+
* The bzero() function erases the data in the n bytes of the memory
123+
* starting at the location pointed to, by writing zeros (bytes
124+
* containing '\0') to that area. The variables are emptied and then
125+
* ready for use
126+
*
127+
* The fork function call is used to create a child and parent process
128+
* which run and execute code simultaneously
129+
*
130+
* The child process is used to send data and after doing so
131+
* sleeps for 5 seconds to wait for the parent to receive data
132+
*
133+
* The parent process is used to receive data and after doing so
134+
* sleeps for 5 seconds to wait for the child to send data
135+
*
136+
* The server and client can communicate indefinitely till one of them
137+
* exits the connection
138+
*
139+
* Since the exchange of information between the server and client takes
140+
* place simultaneously this represents FULL DUPLEX COMMUNICATION
141+
*/
142+
pid_t pid;
143+
pid = fork();
144+
if (pid == 0) /// Value of 0 is for child process
145+
{
146+
while (1)
147+
{
148+
bzero(&sendbuff, sizeof(sendbuff));
149+
printf("\nType message here: ");
150+
fgets(sendbuff, 1024, stdin);
151+
send(sockfd, sendbuff, strlen(sendbuff) + 1, 0);
152+
printf("\nMessage sent!\n");
153+
sleep(5);
154+
// break;
155+
}
156+
}
157+
else /// Parent Process
158+
{
159+
while (1)
160+
{
161+
bzero(&recvbuff, sizeof(recvbuff));
162+
recv(sockfd, recvbuff, sizeof(recvbuff), 0);
163+
printf("\nSERVER: %s\n", recvbuff);
164+
sleep(5);
165+
// break;
166+
}
167+
}
168+
169+
/// Close Socket
170+
close(sockfd);
171+
printf("Client is offline...\n");
172+
return 0;
173+
}
+195
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
/**
2+
* @file
3+
* @author [NVombat](https://github.com/NVombat)
4+
* @brief Server-side implementation of [TCP Full Duplex
5+
* Communication](http://www.tcpipguide.com/free/t_SimplexFullDuplexandHalfDuplexOperation.htm)
6+
* @see tcp_full_duplex_server.c
7+
*
8+
* @details
9+
* The algorithm is based on the simple TCP client and server model. However,
10+
* instead of the server only sending and the client only receiving data,
11+
* The server and client can both send and receive data simultaneously. This is
12+
* implemented by using the `fork` function call so that in the server the child
13+
* process can recieve data and parent process can send data, and in the client
14+
* the child process can send data and the parent process can receive data. It
15+
* runs an infinite loop and can send and receive messages indefinitely until
16+
* the user exits the loop. In this way, the Full Duplex Form of communication
17+
* can be represented using the TCP server-client model & socket programming
18+
*/
19+
20+
#include <arpa/inet.h> /// For the type in_addr_t and in_port_t
21+
#include <netdb.h> /// For structures returned by the network database library - formatted internet addresses and port numbers
22+
#include <netinet/in.h> /// For in_addr and sockaddr_in structures
23+
#include <stdint.h> /// For specific bit size values of variables
24+
#include <stdio.h> /// Variable types, several macros, and various functions for performing input and output
25+
#include <stdlib.h> /// Variable types, several macros, and various functions for performing general functions
26+
#include <string.h> /// Various functions for manipulating arrays of characters
27+
#include <sys/socket.h> /// For macro definitions related to the creation of sockets
28+
#include <sys/types.h> /// For definitions to allow for the porting of BSD programs
29+
#include <unistd.h> /// For miscellaneous symbolic constants and types, and miscellaneous functions
30+
31+
#define PORT 10000 /// Define port over which communication will take place
32+
33+
/**
34+
* @brief Utility function used to print an error message to `stderr`.
35+
* It prints `str` and an implementation-defined error
36+
* message corresponding to the global variable `errno`.
37+
* @returns void
38+
*/
39+
void error()
40+
{
41+
perror("Socket Creation Failed");
42+
exit(EXIT_FAILURE);
43+
}
44+
45+
/**
46+
* @brief Main function
47+
* @returns 0 on exit
48+
*/
49+
int main()
50+
{
51+
/** Variable Declarations */
52+
uint32_t sockfd,
53+
conn; ///< socket descriptors - Like file handles but for sockets
54+
char recvbuff[1024],
55+
sendbuff[1024]; ///< character arrays to read and store string data
56+
/// for communication
57+
58+
struct sockaddr_in server_addr,
59+
client_addr; ///< asic structures for all syscalls and functions that
60+
/// deal with internet addresses. Structures for handling
61+
/// internet addresses
62+
socklen_t ClientLen; /// size of address
63+
64+
/**
65+
* The TCP socket is created using the socket function
66+
*
67+
* AF_INET (Family) - it is an address family that is used to designate the
68+
* type of addresses that your socket can communicate with
69+
*
70+
* SOCK_STREAM (Type) - Indicates TCP Connection - A stream socket provides
71+
* for the bidirectional, reliable, sequenced, and unduplicated flow of data
72+
* without record boundaries. Aside from the bidirectionality of data flow,
73+
* a pair of connected stream sockets provides an interface nearly identical
74+
* to pipes
75+
*
76+
* 0 (Protocol) - Specifies a particular protocol to be used with the
77+
* socket. Specifying a protocol of 0 causes socket() to use an unspecified
78+
* default protocol appropriate for the requested socket type
79+
*/
80+
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
81+
{
82+
error(); ///< Error if the socket descriptor has a value lower than 0 -
83+
/// socket wasnt created
84+
}
85+
86+
/**
87+
* Server Address Information
88+
*
89+
* The bzero() function erases the data in the n bytes of the memory
90+
* starting at the location pointed to, by writing zeros (bytes
91+
* containing '\0') to that area
92+
*
93+
* We bind the server_addr to the internet address and port number thus
94+
* giving our socket an identity with an address and port where it can
95+
* listen for connections
96+
*
97+
* htons - The htons() function translates a short integer from host byte
98+
* order to network byte order
99+
*
100+
* htonl - The htonl() function translates a long integer from host byte
101+
* order to network byte order
102+
*
103+
* These functions are necessary so that the binding of address and port
104+
* takes place with data in the correct format
105+
*/
106+
bzero(&server_addr, sizeof(server_addr));
107+
server_addr.sin_family = AF_INET;
108+
server_addr.sin_port = htons(PORT);
109+
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
110+
111+
printf("Server is running...\n");
112+
113+
/**
114+
* This binds the socket descriptor to the server thus enabling the server
115+
* to listen for connections and communicate with other clients
116+
*/
117+
if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
118+
{
119+
error(); /// If binding is unsuccessful
120+
}
121+
/**
122+
* This is to listen for clients or connections made to the server
123+
*
124+
* The limit is currently at 5 but can be increased to listen for
125+
* more connections
126+
*
127+
* It listens to connections through the socket descriptor
128+
*/
129+
listen(sockfd, 5);
130+
131+
printf("Server is listening...\n");
132+
133+
/**
134+
* When a connection is found, a socket is created and connection is
135+
* accepted and established through the socket descriptor
136+
*/
137+
conn = accept(sockfd, (struct sockaddr *)NULL, NULL);
138+
139+
printf("Server is connected...\n");
140+
141+
/**
142+
* Communication between client and server
143+
*
144+
* The bzero() function erases the data in the n bytes of the memory
145+
* starting at the location pointed to, by writing zeros (bytes
146+
* containing '\0') to that area. The variables are emptied and then
147+
* ready for use
148+
*
149+
* The fork function call is used to create a child and parent process
150+
* which run and execute code simultaneously
151+
*
152+
* The child process is used to receive data and after doing so
153+
* sleeps for 5 seconds to wait for the parent to send data
154+
*
155+
* The parent process is used to send data and after doing so
156+
* sleeps for 5 seconds to wait for the child to receive data
157+
*
158+
* The server and client can communicate indefinitely till one of them
159+
* exits the connection
160+
*
161+
* Since the exchange of information between the server and client takes
162+
* place simultaneously this represents FULL DUPLEX COMMUNICATION
163+
*/
164+
pid_t pid;
165+
pid = fork();
166+
if (pid == 0) /// Value of 0 is for child process
167+
{
168+
while (1)
169+
{
170+
bzero(&recvbuff, sizeof(recvbuff));
171+
recv(conn, recvbuff, sizeof(recvbuff), 0);
172+
printf("\nCLIENT : %s\n", recvbuff);
173+
sleep(5);
174+
// break;
175+
}
176+
}
177+
else /// Parent process
178+
{
179+
while (1)
180+
{
181+
bzero(&sendbuff, sizeof(sendbuff));
182+
printf("\nType message here: ");
183+
fgets(sendbuff, 1024, stdin);
184+
send(conn, sendbuff, strlen(sendbuff) + 1, 0);
185+
printf("\nMessage Sent!\n");
186+
sleep(5);
187+
// break;
188+
}
189+
}
190+
191+
/// Close socket
192+
close(sockfd);
193+
printf("Server is offline...\n");
194+
return 0;
195+
}

0 commit comments

Comments
 (0)