Simple Hello Server/Client program

This commit is contained in:
2023-11-15 00:01:36 +05:30
commit d1c0a6b0f1
15 changed files with 308 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="Client" />
<Option pch_mode="2" />
<Option compiler="gcc" />
<Build>
<Target title="Debug">
<Option output="bin/Debug/Client" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Debug/" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-g" />
</Compiler>
</Target>
<Target title="Release">
<Option output="bin/Release/Client" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Release/" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-O2" />
</Compiler>
<Linker>
<Add option="-s" />
</Linker>
</Target>
</Build>
<Compiler>
<Add option="-Wall" />
<Add option="-fexceptions" />
</Compiler>
<Unit filename="main.cpp" />
<Extensions />
</Project>
</CodeBlocks_project_file>

View File

@@ -0,0 +1,52 @@
//Client side program in C/C++
#include <stdint.h>
#include <netinet/ip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
using namespace std;
static void msg( const char* msg){
fprintf(stderr, "%s\n", msg);
}
static void die(const char* msg){
int err = errno;
fprintf(stderr, "[%d] %s\n", err,msg);
abort();
}
int main(){
int fd = socket(AF_INET, SOCK_STREAM, 0);
if( fd < 0 ){
die("socket()");
}
struct sockaddr_in addr = {};
addr.sin_family = AF_INET;
addr.sin_port = ntohs(1234);
addr.sin_addr.s_addr = ntohl(INADDR_LOOPBACK);// 127.0.0.1
int rv = connect(fd, (const struct sockaddr*)&addr, sizeof(addr));
if( rv ){
die("connect");
}
char msg[] = "hello";
write(fd, msg, strlen(msg));
char rbuf[64] = {};
ssize_t n = read(fd, rbuf , sizeof(rbuf) - 1);
if( n < 0 ){
die("read");
}
printf("server says: %s\n", rbuf);
close(fd);
return 0;
}

View File

@@ -0,0 +1,12 @@
# depslib dependency file v1.0
1699986008 source:/home/hizenberg/Desktop/My Own Redis/Server-Client Program/Client/Client.cpp
<stdint.h>
<netinet/ip.h>
<stdio.h>
<stdlib.h>
<string.h>
<sys/socket.h>
<unistd.h>
<errno.h>
<arpa/inet.h>

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="Server" />
<Option pch_mode="2" />
<Option compiler="gcc" />
<Build>
<Target title="Debug">
<Option output="bin/Debug/Server" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Debug/" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-g" />
</Compiler>
</Target>
<Target title="Release">
<Option output="bin/Release/Server" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Release/" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-O2" />
</Compiler>
<Linker>
<Add option="-s" />
</Linker>
</Target>
</Build>
<Compiler>
<Add option="-Wall" />
<Add option="-fexceptions" />
</Compiler>
<Unit filename="main.cpp" />
<Extensions />
</Project>
</CodeBlocks_project_file>

View File

@@ -0,0 +1,86 @@
//Server side Program in C/C++
#include <stdint.h>
#include <netinet/ip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
static void msg( const char* msg){
fprintf(stderr, "%s\n", msg);
}
static void die(const char* msg){
int err = errno;
fprintf(stderr, "[%d] %s\n", err,msg);
abort();
}
static void do_something(int connfd){
char rbuf[64] = {};
ssize_t n = read(connfd, rbuf, sizeof(rbuf) - 1);
if( n < 0 ){
msg("read() error");
return;
}
printf("Client says: %s\n",rbuf);
char wbuf[] = "world";
write(connfd , wbuf, strlen(wbuf));
}
int main(){
//syscall to return integer for socket communication from kernel
int fd = socket(AF_INET, SOCK_STREAM , 0);
if( fd < 0 ){
die("socket()");
}
//Set the option in various layer which will establish communication.
int val = 1;
setsockopt(fd, SOL_SOCKET , SO_REUSEADDR, &val , sizeof(val));
//bind, dealing wih IPv4 addresses
struct sockaddr_in addr = {};
addr.sin_family = AF_INET;
addr.sin_port = ntohs(1234);
addr.sin_addr.s_addr = ntohl(0);// wildcard address 0.0.0.0
int rv = bind(fd, (const sockaddr*)&addr, sizeof(addr));
if(rv){
die("bind()");
}
//listen
rv = listen(fd , SOMAXCONN);
if( rv ){
die("listen()");
}
//Looping to connect to each connection.
while(true){
//accept
struct sockaddr_in client_addr = {};
socklen_t socklen = sizeof( client_addr );
int connfd = accept(fd , (struct sockaddr*)& client_addr, &socklen);
if( connfd < 0 ){
//error
printf("Error encountered while connecting with client.");
}
do_something(connfd);
close(connfd);
}
return 0;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,36 @@
socket() -> this is a syscall which returns an fd.
fd - It is like a integer which is like an ID used by kernel. It is basically related
to kernel functionality.
bind() -> It is used to bind the address to the fd.
-> The address is which we want to connect with.
listen() -> listen helps to establish connection with that address.
accept() -> when connection is made my client, it returns an fd which represents the established connection.
WORKFLOW OF SERVER (PSEUDO CODE):
fd = socket();
bind(fd,address)
listen(fd)
while(true)
conn_fd = accept(fd)
/**************/
do something with conn_fd
doing something in this connection
/**************/
close(conn_fd)
connect() -> take the fd from client side and make the connection from the address that
-> the address is of the server side.
WORKFLOW OF CLIENT (PSEUDO CODE)
fd = socket()
connect(fd,address)
/*********/
doing something in the connection/
/*********/
close(fd)

View File

@@ -0,0 +1,33 @@
Starting of client and server.
1. First we need fd using socket()
int fd = socket(AF_INET,SOCK_STREAM,0);
->AF_INET = It is used to provide IPv4
NOTE: AF_INET6 = It is used to provide IPv6 or dual-stack socket.
->SOCK_STREAM = It is used to set the TCP protocol.
2. NEW SYSTEM CALL
setsocketopt()
-> There are various layer of network communication and each layer have various option, from which we pick one to
configure the network communication.
-> This syscall is to set those option
IMPORTANT: SO_REUSEADDR-> It is an option to reuse the same address when the process(communication) is restarted.
-> Risk of using it.
# If the previous connection using the same address didn't took all the packets and the process got closed
before taking it, the same address might be used by the same program with new instance of process or by another
program with new instance of process. This rouge packets is intented to send it to the address which is in reuse.
This cause problem. This problem also make it hackable.
NEW TERM: WILDCARD ADDRESS -> when we use sockets, the communication is design to between two process only.
Not allowing multicast or multiple communication. To establish this multiple communication we use wildcard address.
This is used on server-side program.
3. read() and write()
It returns number of read and written bytes.

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_workspace_file>
<Workspace title="Workspace">
<Project filename="Server/Server.cbp" />
<Project filename="Client/Client.cbp" />
</Workspace>
</CodeBlocks_workspace_file>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_workspace_layout_file>
<FileVersion major="1" minor="0" />
<ActiveProject path="Server/Server.cbp" />
<PreferredTarget name="Debug" />
</CodeBlocks_workspace_layout_file>