refactor(remove-comments): unnecessary comments were removed and also bugs undefined variables were created in /client_server/fork.h, /client_server/udp_client.c and /client_server/udp_server.c

This commit is contained in:
Allan Julie Fontes de Oliveira 2024-11-04 18:24:11 -03:00
parent e5dad3fa8d
commit 60abb8fea7
13 changed files with 209 additions and 937 deletions

14
.gitignore vendored
View File

@ -4,3 +4,17 @@
.vscode/ .vscode/
build/ build/
git_diff.txt git_diff.txt
*.filters
*.vcxproj
*.sln
CMakeCache.txt
cmake_install.cmake
*.log
*.stamp
*.stamp.list
*.stamp.depend
*.check_cache
*.tlog
*.bin
CMakeFiles/
output/

View File

@ -1,21 +1,6 @@
/*
* Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
* Copyright (C) 2007 - INRIA
*
* Copyright (C) 2012 - 2016 - Scilab Enterprises
*
* This file is hereby licensed under the terms of the GNU GPL v2.0,
* pursuant to article 5.3.4 of the CeCILL v.2.1.
* This file was originally licensed under the terms of the CeCILL v2.1,
* and continues to be available under such terms.
* For more information, see the COPYING file which you should have received
* along with this program.
*
*/
#ifndef __BOOL_H__ #ifndef __BOOL_H__
#define __BOOL_H__ #define __BOOL_H__
/* define boolean type */
#ifdef BOOL #ifdef BOOL
#undef BOOL #undef BOOL
#endif #endif
@ -28,8 +13,7 @@
#undef FALSE #undef FALSE
#endif #endif
#ifndef _MSC_VER
#ifndef _MSC_VER
typedef enum typedef enum
{ {
FALSE = 0, FALSE = 0,
@ -37,19 +21,15 @@ typedef enum
} BOOL; } BOOL;
#else #else
/* Please notice that BOOL is defined in <windef.h> */
/* BUT windef.h includes all others windows include */
/* it is better to redefine as */
typedef int BOOL; typedef int BOOL;
#define FALSE 0 #define FALSE 0
#define TRUE 1 #define TRUE 1
#endif #endif
/* converts BOOL to bool */
#define BOOLtobool(w) ((w != FALSE) ? true : false)
/* converts bool to BOOL */ #define BOOLtobool(w) ((w != FALSE) ? true : false)
#define booltoBOOL(w) ((w == true) ? TRUE : FALSE)
#endif /* __BOOL_H__ */ #define booltoBOOL(w) ((w == true) ? TRUE : FALSE)
/*--------------------------------------------------------------------------*/
#endif

View File

@ -1,39 +1,26 @@
/**
* @file
* @author [Nairit11](https://github.com/Nairit11)
* @author [Krishna Vedala](https://github.com/kvedala)
* @brief Client side implementation of Server-Client system.
* @see client_server/server.c
*/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef _WIN32 // if compiling for Windows #ifdef _WIN32
#define _WINSOCK_DEPRECATED_NO_WARNINGS // will make the code invalid for next #define _WINSOCK_DEPRECATED_NO_WARNINGS
// MSVC compiler versions
#include <winsock2.h> #include <winsock2.h>
#define bzero(b, len) \ #define bzero(b, len) (memset((b), '\0', (len)), (void)0)
(memset((b), '\0', (len)), (void)0) /**< BSD name not in windows */ #define read(a, b, c) recv(a, b, c, 0)
#define read(a, b, c) recv(a, b, c, 0) /**< map BSD name to Winsock */ #define write(a, b, c) send(a, b, c, 0)
#define write(a, b, c) send(a, b, c, 0) /**< map BSD name to Winsock */ #define close closesocket
#define close closesocket /**< map BSD name to Winsock */ #else
#else // if not windows platform
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
#endif #endif
#define MAX 80 /**< max. characters per message */ #define MAX 80
#define PORT 8080 /**< port number to connect to */ #define PORT 8080
#define SA struct sockaddr /**< shortname for sockaddr */ #define SA struct sockaddr
/**
* Continuous loop to send and receive over the socket.
* Exits when "exit" is sent from commandline.
* @param sockfd socket handle number
*/
void func(int sockfd) void func(int sockfd)
{ {
char buff[MAX]; char buff[MAX];
@ -60,17 +47,12 @@ void func(int sockfd)
} }
#ifdef _WIN32 #ifdef _WIN32
/** Cleanup function will be automatically called on program exit */
void cleanup() { WSACleanup(); } void cleanup() { WSACleanup(); }
#endif #endif
/**
* @brief Driver code
*/
int main() int main()
{ {
#ifdef _WIN32 #ifdef _WIN32
// when using winsock2.h, startup required
WSADATA wsData; WSADATA wsData;
if (WSAStartup(MAKEWORD(2, 2), &wsData) != 0) if (WSAStartup(MAKEWORD(2, 2), &wsData) != 0)
{ {
@ -78,13 +60,12 @@ int main()
return 0; return 0;
} }
atexit(cleanup); // register at-exit function atexit(cleanup);
#endif #endif
int sockfd, connfd; int sockfd, connfd;
struct sockaddr_in servaddr, cli; struct sockaddr_in servaddr, cli;
// socket create and verification
sockfd = socket(AF_INET, SOCK_STREAM, 0); sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) if (sockfd == -1)
{ {
@ -97,12 +78,10 @@ int main()
} }
bzero(&servaddr, sizeof(servaddr)); bzero(&servaddr, sizeof(servaddr));
// assign IP, PORT
servaddr.sin_family = AF_INET; servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servaddr.sin_port = htons(PORT); servaddr.sin_port = htons(PORT);
// connect the client socket to server socket
if (connect(sockfd, (SA *)&servaddr, sizeof(servaddr)) != 0) if (connect(sockfd, (SA *)&servaddr, sizeof(servaddr)) != 0)
{ {
printf("connection with the server failed...\n"); printf("connection with the server failed...\n");
@ -113,10 +92,8 @@ int main()
printf("connected to the server..\n"); printf("connected to the server..\n");
} }
// function for chat
func(sockfd); func(sockfd);
// close the socket
close(sockfd); close(sockfd);
return 0; return 0;
} }

View File

@ -1,43 +1,22 @@
/*
* Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
* Copyright (C) DIGITEO - 2010 - Allan CORNET
*
* Copyright (C) 2012 - 2016 - Scilab Enterprises
*
* This file is hereby licensed under the terms of the GNU GPL v2.0,
* pursuant to article 5.3.4 of the CeCILL v.2.1.
* This file was originally licensed under the terms of the CeCILL v2.1,
* and continues to be available under such terms.
* For more information, see the COPYING file which you should have received
* along with this program.
*
*/
/*--------------------------------------------------------------------------*/
#ifndef __FORK_H__ #ifndef __FORK_H__
#define __FORK_H__ #define __FORK_H__
/* http://technet.microsoft.com/en-us/library/bb497007.aspx */
/* http://undocumented.ntinternals.net/ */
#include <setjmp.h> #include <setjmp.h>
#include <windows.h> #include <windows.h>
#include "bool.h" #include "bool.h"
/**
* simulate fork on Windows
*/
int fork(void); int fork(void);
/**
* check if symbols to simulate fork are present
* and load these symbols
*/
BOOL haveLoadedFunctionsForFork(void); BOOL haveLoadedFunctionsForFork(void);
/*--------------------------------------------------------------------------*/
typedef LONG NTSTATUS; typedef LONG NTSTATUS;
/*--------------------------------------------------------------------------*/ typedef enum _THREAD_INFORMATION_CLASS
{
ThreadBasicInformation = 0,
ThreadQuerySetWin32StartAddress = 9,
ThreadMemoryPriority = 13
} THREAD_INFORMATION_CLASS;
typedef struct _SYSTEM_HANDLE_INFORMATION typedef struct _SYSTEM_HANDLE_INFORMATION
{ {
ULONG ProcessId; ULONG ProcessId;
@ -47,17 +26,17 @@ typedef struct _SYSTEM_HANDLE_INFORMATION
PVOID Object; PVOID Object;
ACCESS_MASK GrantedAccess; ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
/*--------------------------------------------------------------------------*/
typedef struct _OBJECT_ATTRIBUTES typedef struct _OBJECT_ATTRIBUTES
{ {
ULONG Length; ULONG Length;
HANDLE RootDirectory; HANDLE RootDirectory;
PVOID /* really PUNICODE_STRING */ ObjectName; PVOID ObjectName;
ULONG Attributes; ULONG Attributes;
PVOID SecurityDescriptor; /* type SECURITY_DESCRIPTOR */ PVOID SecurityDescriptor;
PVOID SecurityQualityOfService; /* type SECURITY_QUALITY_OF_SERVICE */ PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
/*--------------------------------------------------------------------------*/
typedef enum _MEMORY_INFORMATION_ typedef enum _MEMORY_INFORMATION_
{ {
MemoryBasicInformation, MemoryBasicInformation,
@ -65,13 +44,13 @@ typedef enum _MEMORY_INFORMATION_
MemorySectionName, MemorySectionName,
MemoryBasicVlmInformation MemoryBasicVlmInformation
} MEMORY_INFORMATION_CLASS; } MEMORY_INFORMATION_CLASS;
/*--------------------------------------------------------------------------*/
typedef struct _CLIENT_ID typedef struct _CLIENT_ID
{ {
HANDLE UniqueProcess; HANDLE UniqueProcess;
HANDLE UniqueThread; HANDLE UniqueThread;
} CLIENT_ID, *PCLIENT_ID; } CLIENT_ID, *PCLIENT_ID;
/*--------------------------------------------------------------------------*/
typedef struct _USER_STACK typedef struct _USER_STACK
{ {
PVOID FixedStackBase; PVOID FixedStackBase;
@ -80,11 +59,11 @@ typedef struct _USER_STACK
PVOID ExpandableStackLimit; PVOID ExpandableStackLimit;
PVOID ExpandableStackBottom; PVOID ExpandableStackBottom;
} USER_STACK, *PUSER_STACK; } USER_STACK, *PUSER_STACK;
/*--------------------------------------------------------------------------*/
typedef LONG KPRIORITY; typedef LONG KPRIORITY;
typedef ULONG_PTR KAFFINITY; typedef ULONG_PTR KAFFINITY;
typedef KAFFINITY *PKAFFINITY; typedef KAFFINITY *PKAFFINITY;
/*--------------------------------------------------------------------------*/
typedef struct _THREAD_BASIC_INFORMATION typedef struct _THREAD_BASIC_INFORMATION
{ {
NTSTATUS ExitStatus; NTSTATUS ExitStatus;
@ -94,22 +73,22 @@ typedef struct _THREAD_BASIC_INFORMATION
KPRIORITY Priority; KPRIORITY Priority;
KPRIORITY BasePriority; KPRIORITY BasePriority;
} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION; } THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;
/*--------------------------------------------------------------------------*/
typedef enum _SYSTEM_INFORMATION_CLASS typedef enum _SYSTEM_INFORMATION_CLASS
{ {
SystemHandleInformation = 0x10 SystemHandleInformation = 0x10
} SYSTEM_INFORMATION_CLASS; } SYSTEM_INFORMATION_CLASS;
/*--------------------------------------------------------------------------*/
typedef NTSTATUS(NTAPI *ZwWriteVirtualMemory_t)( typedef NTSTATUS(NTAPI *ZwWriteVirtualMemory_t)(
IN HANDLE ProcessHandle, IN PVOID BaseAddress, IN PVOID Buffer, IN HANDLE ProcessHandle, IN PVOID BaseAddress, IN PVOID Buffer,
IN ULONG NumberOfBytesToWrite, OUT PULONG NumberOfBytesWritten OPTIONAL); IN ULONG NumberOfBytesToWrite, OUT PULONG NumberOfBytesWritten OPTIONAL);
/*--------------------------------------------------------------------------*/
typedef NTSTATUS(NTAPI *ZwCreateProcess_t)( typedef NTSTATUS(NTAPI *ZwCreateProcess_t)(
OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE InheriteFromProcessHandle, IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE InheriteFromProcessHandle,
IN BOOLEAN InheritHandles, IN HANDLE SectionHandle OPTIONAL, IN BOOLEAN InheritHandles, IN HANDLE SectionHandle OPTIONAL,
IN HANDLE DebugPort OPTIONAL, IN HANDLE ExceptionPort OPTIONAL); IN HANDLE DebugPort OPTIONAL, IN HANDLE ExceptionPort OPTIONAL);
/*--------------------------------------------------------------------------*/
typedef NTSTATUS(WINAPI *ZwQuerySystemInformation_t)( typedef NTSTATUS(WINAPI *ZwQuerySystemInformation_t)(
SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation,
ULONG SystemInformationLength, PULONG ReturnLength); ULONG SystemInformationLength, PULONG ReturnLength);
@ -118,7 +97,7 @@ typedef NTSTATUS(NTAPI *ZwQueryVirtualMemory_t)(
IN MEMORY_INFORMATION_CLASS MemoryInformationClass, IN MEMORY_INFORMATION_CLASS MemoryInformationClass,
OUT PVOID MemoryInformation, IN ULONG MemoryInformationLength, OUT PVOID MemoryInformation, IN ULONG MemoryInformationLength,
OUT PULONG ReturnLength OPTIONAL); OUT PULONG ReturnLength OPTIONAL);
/*--------------------------------------------------------------------------*/
typedef NTSTATUS(NTAPI *ZwGetContextThread_t)(IN HANDLE ThreadHandle, typedef NTSTATUS(NTAPI *ZwGetContextThread_t)(IN HANDLE ThreadHandle,
OUT PCONTEXT Context); OUT PCONTEXT Context);
typedef NTSTATUS(NTAPI *ZwCreateThread_t)( typedef NTSTATUS(NTAPI *ZwCreateThread_t)(
@ -126,7 +105,7 @@ typedef NTSTATUS(NTAPI *ZwCreateThread_t)(
IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE ProcessHandle, IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE ProcessHandle,
OUT PCLIENT_ID ClientId, IN PCONTEXT ThreadContext, OUT PCLIENT_ID ClientId, IN PCONTEXT ThreadContext,
IN PUSER_STACK UserStack, IN BOOLEAN CreateSuspended); IN PUSER_STACK UserStack, IN BOOLEAN CreateSuspended);
/*--------------------------------------------------------------------------*/
typedef NTSTATUS(NTAPI *ZwResumeThread_t)(IN HANDLE ThreadHandle, typedef NTSTATUS(NTAPI *ZwResumeThread_t)(IN HANDLE ThreadHandle,
OUT PULONG SuspendCount OPTIONAL); OUT PULONG SuspendCount OPTIONAL);
typedef NTSTATUS(NTAPI *ZwClose_t)(IN HANDLE ObjectHandle); typedef NTSTATUS(NTAPI *ZwClose_t)(IN HANDLE ObjectHandle);
@ -134,7 +113,7 @@ typedef NTSTATUS(NTAPI *ZwQueryInformationThread_t)(
IN HANDLE ThreadHandle, IN THREAD_INFORMATION_CLASS ThreadInformationClass, IN HANDLE ThreadHandle, IN THREAD_INFORMATION_CLASS ThreadInformationClass,
OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength, OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength,
OUT PULONG ReturnLength OPTIONAL); OUT PULONG ReturnLength OPTIONAL);
/*--------------------------------------------------------------------------*/
static ZwCreateProcess_t ZwCreateProcess = NULL; static ZwCreateProcess_t ZwCreateProcess = NULL;
static ZwQuerySystemInformation_t ZwQuerySystemInformation = NULL; static ZwQuerySystemInformation_t ZwQuerySystemInformation = NULL;
static ZwQueryVirtualMemory_t ZwQueryVirtualMemory = NULL; static ZwQueryVirtualMemory_t ZwQueryVirtualMemory = NULL;
@ -144,25 +123,23 @@ static ZwResumeThread_t ZwResumeThread = NULL;
static ZwClose_t ZwClose = NULL; static ZwClose_t ZwClose = NULL;
static ZwQueryInformationThread_t ZwQueryInformationThread = NULL; static ZwQueryInformationThread_t ZwQueryInformationThread = NULL;
static ZwWriteVirtualMemory_t ZwWriteVirtualMemory = NULL; static ZwWriteVirtualMemory_t ZwWriteVirtualMemory = NULL;
/*--------------------------------------------------------------------------*/
#define NtCurrentProcess() ((HANDLE)-1) #define NtCurrentProcess() ((HANDLE) - 1)
#define NtCurrentThread() ((HANDLE)-2) #define NtCurrentThread() ((HANDLE) - 2)
/* we use really the Nt versions - so the following is just for completeness */
#define ZwCurrentProcess() NtCurrentProcess() #define ZwCurrentProcess() NtCurrentProcess()
#define ZwCurrentThread() NtCurrentThread() #define ZwCurrentThread() NtCurrentThread()
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) #define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
/*--------------------------------------------------------------------------*/
/* setjmp env for the jump back into the fork() function */
static jmp_buf jenv; static jmp_buf jenv;
/*--------------------------------------------------------------------------*/
/* entry point for our child thread process - just longjmp into fork */
static int child_entry(void) static int child_entry(void)
{ {
longjmp(jenv, 1); longjmp(jenv, 1);
return 0; return 0;
} }
/*--------------------------------------------------------------------------*/
static BOOL haveLoadedFunctionsForFork(void) static BOOL haveLoadedFunctionsForFork(void)
{ {
HMODULE ntdll = GetModuleHandle("ntdll"); HMODULE ntdll = GetModuleHandle("ntdll");
@ -214,7 +191,7 @@ static BOOL haveLoadedFunctionsForFork(void)
} }
return FALSE; return FALSE;
} }
/*--------------------------------------------------------------------------*/
int fork(void) int fork(void)
{ {
HANDLE hProcess = 0, hThread = 0; HANDLE hProcess = 0, hThread = 0;
@ -230,26 +207,19 @@ int fork(void)
if (setjmp(jenv) != 0) if (setjmp(jenv) != 0)
{ {
return 0; /* return as a child */ return 0;
} }
/* check whether the entry points are initilized and get them if necessary
*/
if (!ZwCreateProcess && !haveLoadedFunctionsForFork()) if (!ZwCreateProcess && !haveLoadedFunctionsForFork())
{ {
return -1; return -1;
} }
/* create forked process */
ZwCreateProcess(&hProcess, PROCESS_ALL_ACCESS, &oa, NtCurrentProcess(), ZwCreateProcess(&hProcess, PROCESS_ALL_ACCESS, &oa, NtCurrentProcess(),
TRUE, 0, 0, 0); TRUE, 0, 0, 0);
/* set the Eip for the child process to our child function */
ZwGetContextThread(NtCurrentThread(), &context); ZwGetContextThread(NtCurrentThread(), &context);
/* In x64 the Eip and Esp are not present, their x64 counterparts are Rip
and Rsp respectively.
*/
#if _WIN64 #if _WIN64
context.Rip = (ULONG)child_entry; context.Rip = (ULONG)child_entry;
#else #else
@ -270,11 +240,9 @@ int fork(void)
stack.ExpandableStackLimit = mbi.BaseAddress; stack.ExpandableStackLimit = mbi.BaseAddress;
stack.ExpandableStackBottom = mbi.AllocationBase; stack.ExpandableStackBottom = mbi.AllocationBase;
/* create thread using the modified context and stack */
ZwCreateThread(&hThread, THREAD_ALL_ACCESS, &oa, hProcess, &cid, &context, ZwCreateThread(&hThread, THREAD_ALL_ACCESS, &oa, hProcess, &cid, &context,
&stack, TRUE); &stack, TRUE);
/* copy exception table */
ZwQueryInformationThread(NtCurrentThread(), ThreadMemoryPriority, &tbi, ZwQueryInformationThread(NtCurrentThread(), ThreadMemoryPriority, &tbi,
sizeof tbi, 0); sizeof tbi, 0);
tib = (PNT_TIB)tbi.TebBaseAddress; tib = (PNT_TIB)tbi.TebBaseAddress;
@ -283,16 +251,12 @@ int fork(void)
ZwWriteVirtualMemory(hProcess, tbi.TebBaseAddress, &tib->ExceptionList, ZwWriteVirtualMemory(hProcess, tbi.TebBaseAddress, &tib->ExceptionList,
sizeof tib->ExceptionList, 0); sizeof tib->ExceptionList, 0);
/* start (resume really) the child */
ZwResumeThread(hThread, 0); ZwResumeThread(hThread, 0);
/* clean up */
ZwClose(hThread); ZwClose(hThread);
ZwClose(hProcess); ZwClose(hProcess);
/* exit with child's pid */
return (int)cid.UniqueProcess; return (int)cid.UniqueProcess;
} }
#endif /* __FORK_H__ */ #endif
/*--------------------------------------------------------------------------*/

View File

@ -1,113 +1,45 @@
/**
* @file
* @author [NVombat](https://github.com/NVombat)
* @brief Client-side implementation of [Remote Command
* Execution Using
* UDP](https://www.imperva.com/learn/ddos/udp-user-datagram-protocol/)
* @see remote_command_exec_udp_server.c
*
* @details
* The algorithm is based on the simple UDP client and server model. It
* runs an infinite loop which takes user input and sends it to the server
* for execution. The server receives the commands and executes them
* until the user exits the loop. In this way, Remote Command Execution
* using UDP is shown using the server-client model & socket programming
*/
#ifdef _WIN32 #ifdef _WIN32
#define bzero(b, len) \ #define bzero(b, len) (memset((b), '\0', (len)), (void)0)
(memset((b), '\0', (len)), (void)0) /**< BSD name not in windows */
#define close _close #define close _close
#include <Ws2tcpip.h> #include <Ws2tcpip.h>
#include <io.h> #include <io.h>
#include <winsock2.h> /// For the type in_addr_t and in_port_t #include <winsock2.h>
#else #else
#include <arpa/inet.h> /// For the type in_addr_t and in_port_t #include <arpa/inet.h>
#include <netdb.h> /// For structures returned by the network database library - formatted internet addresses and port numbers #include <netdb.h>
#include <netinet/in.h> /// For in_addr and sockaddr_in structures #include <netinet/in.h>
#include <sys/socket.h> /// For macro definitions related to the creation of sockets #include <sys/socket.h>
#include <sys/types.h> /// For definitions to allow for the porting of BSD programs #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#endif #endif
#include <errno.h> /// To indicate what went wrong if an error occurs #include <errno.h>
#include <stdint.h> /// For specific bit size values of variables #include <stdint.h>
#include <stdio.h> /// Variable types, several macros, and various functions for performing input and output #include <stdio.h>
#include <stdlib.h> /// Variable types, several macros, and various functions for performing general functions #include <stdlib.h>
#include <string.h> /// Various functions for manipulating arrays of characters #include <string.h>
#define PORT 10000 /// Define port over which communication will take place #define PORT 10000
/**
* @brief Utility function used to print an error message to `stderr`.
* It prints `str` and an implementation-defined error
* message corresponding to the global variable `errno`.
* @returns void
*/
void error() void error()
{ {
perror("Socket Creation Failed"); perror("Socket Creation Failed");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/**
* @brief Main function
* @returns 0 on exit
*/
int main() int main()
{ {
/** Variable Declarations */ uint32_t sockfd;
uint32_t char send_msg[1024], recv_msg[1024];
sockfd; ///< socket descriptors - Like file handles but for sockets
char send_msg[1024],
recv_msg[1024]; ///< character arrays to read and store string data
/// for communication
struct sockaddr_in struct sockaddr_in server_addr;
server_addr; ///< basic structures for all syscalls and functions that
/// deal with internet addresses. Structures for handling socklen_t serverLength = sizeof(server_addr);
/// internet addresses
socklen_t serverLength = sizeof(server_addr); ///< length of socket
/**
* The UDP socket is created using the socket function.
*
* AF_INET (Family) - it is an address family that is used to designate the
* type of addresses that your socket can communicate with
*
* SOCK_DGRAM (Type) - Indicates UDP Connection - UDP does not require the
* source and destination to establish a three-way handshake before
* transmission takes place. Additionally, there is no need for an
* end-to-end connection
*
* 0 (Protocol) - Specifies a particular protocol to be used with the
* socket. Specifying a protocol of 0 causes socket() to use an unspecified
* default protocol appropriate for the requested socket type.
*/
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{ {
error(); error();
} }
/**
* Server Address Information
*
* The bzero() function erases the data in the n bytes of the memory
* starting at the location pointed to, by writing zeros (bytes
* containing '\0') to that area.
*
* We bind the server_addr to the internet address and port number thus
* giving our socket an identity with an address and port where it can
* listen for connections
*
* htons - The htons() function translates a short integer from host byte
* order to network byte order
*
* htonl - The htonl() function translates a long integer from host byte
* order to network byte order
*
* These functions are necessary so that the binding of address and port
* takes place with data in the correct format
*/
bzero(&server_addr, sizeof(server_addr)); bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET; server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT); server_addr.sin_port = htons(PORT);
@ -115,29 +47,10 @@ int main()
printf("Client is running...\n"); printf("Client is running...\n");
/**
* Connects the client to the server address using the socket descriptor
* This enables the two to communicate and exchange data
*/
connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)); connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
printf("Client is Connected Successfully...\n"); printf("Client is Connected Successfully...\n");
/**
* Communication between client and server
*
* The client sends data to the server after taking the input
* from the user
*
* The client then receives a response from the server when the
* command has been executed
*
* The server and client can communicate indefinitely till one of them
* exits the connection
*
* The client sends the server a command which it executes thus showing
* remote command execution using UDP
*/
while (1) while (1)
{ {
printf("\nEnter Command To Be Executed Remotely: \n"); printf("\nEnter Command To Be Executed Remotely: \n");
@ -149,7 +62,6 @@ int main()
printf("Server Reply: %s\n", recv_msg); printf("Server Reply: %s\n", recv_msg);
} }
/// Close Socket
close(sockfd); close(sockfd);
printf("Client is offline...\n"); printf("Client is offline...\n");
return 0; return 0;

View File

@ -1,152 +1,57 @@
/**
* @file
* @author [NVombat](https://github.com/NVombat)
* @brief Server-side implementation of [Remote Command
* Execution Using
* UDP](https://www.imperva.com/learn/ddos/udp-user-datagram-protocol/)
* @see remote_command_exec_udp_server.c
*
* @details
* The algorithm is based on the simple UDP client and server model. It
* runs an infinite loop which takes user input and sends it to the server
* for execution. The server receives the commands and executes them
* until the user exits the loop. In this way, Remote Command Execution
* using UDP is shown using the server-client model & socket programming
*/
#ifdef _WIN32 #ifdef _WIN32
#define bzero(b, len) \ #define bzero(b, len) (memset((b), '\0', (len)), (void)0)
(memset((b), '\0', (len)), (void)0) /**< BSD name not in windows */
#define close _close #define close _close
#include <Ws2tcpip.h> #include <Ws2tcpip.h>
#include <io.h> #include <io.h>
#include <winsock2.h> /// For the type in_addr_t and in_port_t #include <winsock2.h>
#else #else
#include <arpa/inet.h> /// For the type in_addr_t and in_port_t #include <arpa/inet.h>
#include <netdb.h> /// For structures returned by the network database library - formatted internet addresses and port numbers #include <netdb.h>
#include <netinet/in.h> /// For in_addr and sockaddr_in structures #include <netinet/in.h>
#include <sys/socket.h> /// For macro definitions related to the creation of sockets #include <sys/socket.h>
#include <sys/types.h> /// For definitions to allow for the porting of BSD programs #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#endif #endif
#include <errno.h> /// To indicate what went wrong if an error occurs #include <errno.h>
#include <stdint.h> /// For specific bit size values of variables #include <stdint.h>
#include <stdio.h> /// Variable types, several macros, and various functions for performing input and output #include <stdio.h>
#include <stdlib.h> /// Variable types, several macros, and various functions for performing general functions #include <stdlib.h>
#include <string.h> /// Various functions for manipulating arrays of characters #include <string.h>
#define PORT 10000 /// Define port over which communication will take place #define PORT 10000
/**
* @brief Utility function used to print an error message to `stderr`.
* It prints `str` and an implementation-defined error
* message corresponding to the global variable `errno`.
* @returns void
*/
void error() void error()
{ {
perror("Socket Creation Failed"); perror("Socket Creation Failed");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/**
* @brief Main function
* @returns 0 on exit
*/
int main() int main()
{ {
/** Variable Declarations */ uint32_t sockfd;
uint32_t char recv_msg[1024], success_message[] = "Command Executed Successfully!\n";
sockfd; ///< socket descriptors - Like file handles but for sockets
char recv_msg[1024],
success_message[] =
"Command Executed Successfully!\n"; ///< character arrays to read
/// and store string data
/// for communication & Success
/// message
struct sockaddr_in server_addr, struct sockaddr_in server_addr, client_addr;
client_addr; ///< basic structures for all syscalls and functions that
/// deal with internet addresses. Structures for handling socklen_t clientLength = sizeof(client_addr);
/// internet addresses
socklen_t clientLength = sizeof(client_addr); /// size of address
/**
* The UDP socket is created using the socket function.
*
* AF_INET (Family) - it is an address family that is used to designate the
* type of addresses that your socket can communicate with
*
* SOCK_DGRAM (Type) - Indicates UDP Connection - UDP does not require the
* source and destination to establish a three-way handshake before
* transmission takes place. Additionally, there is no need for an
* end-to-end connection
*
* 0 (Protocol) - Specifies a particular protocol to be used with the
* socket. Specifying a protocol of 0 causes socket() to use an unspecified
* default protocol appropriate for the requested socket type.
*/
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{ {
error(); error();
} }
/**
* Server Address Information
*
* The bzero() function erases the data in the n bytes of the memory
* starting at the location pointed to, by writing zeros (bytes
* containing '\0') to that area.
*
* We bind the server_addr to the internet address and port number thus
* giving our socket an identity with an address and port where it can
* listen for connections
*
* htons - The htons() function translates a short integer from host byte
* order to network byte order
*
* htonl - The htonl() function translates a long integer from host byte
* order to network byte order
*
* These functions are necessary so that the binding of address and port
* takes place with data in the correct format
*/
bzero(&server_addr, sizeof(server_addr)); bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET; server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT); server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
/**
* This binds the socket descriptor to the server thus enabling the server
* to listen for connections and communicate with other clients
*/
if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
{ {
error(); /// If binding is unsuccessful error();
} }
printf("Server is Connected Successfully...\n"); printf("Server is Connected Successfully...\n");
/**
* Communication between client and server
*
* The bzero() function erases the data in the n bytes of the memory
* starting at the location pointed to, by writing zeros (bytes
* containing '\0') to that area. The variables are emptied and then
* ready for use
*
* The server receives data from the client which is a command. It then
* executes the command.
*
* The client then receives a response from the server when the
* command has been executed
*
* The server and client can communicate indefinitely till one of them
* exits the connection
*
* The client sends the server a command which it executes thus showing
* remote command execution using UDP
*/
while (1) while (1)
{ {
bzero(recv_msg, sizeof(recv_msg)); bzero(recv_msg, sizeof(recv_msg));
@ -159,7 +64,6 @@ int main()
(struct sockaddr *)&client_addr, clientLength); (struct sockaddr *)&client_addr, clientLength);
} }
/// Close socket
close(sockfd); close(sockfd);
printf("Server is offline...\n"); printf("Server is offline...\n");
return 0; return 0;

View File

@ -1,74 +1,53 @@
/**
* @file
* @author [Nairit11](https://github.com/Nairit11)
* @author [Krishna Vedala](https://github.com/kvedala)
* @brief Server side implementation of Server-Client system.
* @see client_server/client.c
*/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
// #ifdef HAS_UNISTD
// #include <unistd.h>
// #endif
#ifdef _WIN32 #ifdef _WIN32
#define _WINSOCK_DEPRECATED_NO_WARNINGS // will make the code invalid for next #define _WINSOCK_DEPRECATED_NO_WARNINGS
// MSVC compiler versions
#include <winsock2.h> #include <winsock2.h>
#define bzero(b, len) \ #define bzero(b, len) (memset((b), '\0', (len)), (void)0)
(memset((b), '\0', (len)), (void)0) /**< BSD name not in windows */ #define read(a, b, c) recv(a, b, c, 0)
#define read(a, b, c) recv(a, b, c, 0) /**< map BSD name to Winsock */ #define write(a, b, c) send(a, b, c, 0)
#define write(a, b, c) send(a, b, c, 0) /**< map BSD name to Winsock */ #define close closesocket
#define close closesocket /**< map BSD name to Winsock */
#else #else
// if not windows platform
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
#endif #endif
#define MAX 80 /**< max. characters per message */ #define MAX 80
#define PORT 8080 /**< port number to connect to */ #define PORT 8080
#define SA struct sockaddr /**< shortname for sockaddr */ #define SA struct sockaddr
#ifdef _WIN32 #ifdef _WIN32
/** Cleanup function will be automatically called on program exit */
void cleanup() { WSACleanup(); } void cleanup() { WSACleanup(); }
#endif #endif
/**
* Continuous loop to send and receive over the socket.
* Exits when "exit" is sent from commandline.
* @param sockfd socket handle number
*/
void func(int sockfd) void func(int sockfd)
{ {
char buff[MAX]; char buff[MAX];
int n; int n;
// infinite loop for chat
for (;;) for (;;)
{ {
bzero(buff, MAX); bzero(buff, MAX);
// read the message from client and copy it in buffer
read(sockfd, buff, sizeof(buff)); read(sockfd, buff, sizeof(buff));
// print buffer which contains the client contents
printf("From client: %s\t To client : ", buff); printf("From client: %s\t To client : ", buff);
bzero(buff, MAX); bzero(buff, MAX);
n = 0; n = 0;
// copy server message in the buffer
while ((buff[n++] = getchar()) != '\n') while ((buff[n++] = getchar()) != '\n')
{ {
; ;
} }
// and send that buffer to client
write(sockfd, buff, sizeof(buff)); write(sockfd, buff, sizeof(buff));
// if msg contains "Exit" then server exit and chat ended.
if (strncmp("exit", buff, 4) == 0) if (strncmp("exit", buff, 4) == 0)
{ {
printf("Server Exit...\n"); printf("Server Exit...\n");
@ -77,11 +56,9 @@ void func(int sockfd)
} }
} }
/** Driver code */
int main() int main()
{ {
#ifdef _WIN32 #ifdef _WIN32
// when using winsock2.h, startup required
WSADATA wsData; WSADATA wsData;
if (WSAStartup(MAKEWORD(2, 2), &wsData) != 0) if (WSAStartup(MAKEWORD(2, 2), &wsData) != 0)
{ {
@ -89,14 +66,13 @@ int main()
return 0; return 0;
} }
atexit(cleanup); // register at-exit function atexit(cleanup);
#endif #endif
int sockfd, connfd; int sockfd, connfd;
unsigned int len; unsigned int len;
struct sockaddr_in servaddr, cli; struct sockaddr_in servaddr, cli;
// socket create and verification
sockfd = socket(AF_INET, SOCK_STREAM, 0); sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) if (sockfd == -1)
{ {
@ -109,12 +85,10 @@ int main()
} }
bzero(&servaddr, sizeof(servaddr)); bzero(&servaddr, sizeof(servaddr));
// assign IP, PORT
servaddr.sin_family = AF_INET; servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(PORT); servaddr.sin_port = htons(PORT);
// Binding newly created socket to given IP and verification
if ((bind(sockfd, (SA *)&servaddr, sizeof(servaddr))) != 0) if ((bind(sockfd, (SA *)&servaddr, sizeof(servaddr))) != 0)
{ {
perror("socket bind failed...\n"); perror("socket bind failed...\n");
@ -125,7 +99,6 @@ int main()
printf("Socket successfully binded..\n"); printf("Socket successfully binded..\n");
} }
// Now server is ready to listen and verification
if ((listen(sockfd, 5)) != 0) if ((listen(sockfd, 5)) != 0)
{ {
perror("Listen failed...\n"); perror("Listen failed...\n");
@ -137,7 +110,6 @@ int main()
} }
len = sizeof(cli); len = sizeof(cli);
// Accept the data packet from client and verification
connfd = accept(sockfd, (SA *)&cli, &len); connfd = accept(sockfd, (SA *)&cli, &len);
if (connfd < 0) if (connfd < 0)
{ {
@ -149,10 +121,8 @@ int main()
printf("server acccept the client...\n"); printf("server acccept the client...\n");
} }
// Function for chatting between client and server
func(connfd); func(connfd);
// After chatting close the socket
close(sockfd); close(sockfd);
return 0; return 0;
} }

View File

@ -1,119 +1,47 @@
/**
* @file
* @author [NVombat](https://github.com/NVombat)
* @brief Client-side implementation of [TCP Full Duplex
* Communication](http://www.tcpipguide.com/free/t_SimplexFullDuplexandHalfDuplexOperation.htm)
* @see tcp_full_duplex_server.c
*
* @details
* The algorithm is based on the simple TCP client and server model. However,
* instead of the server only sending and the client only receiving data,
* The server and client can both send and receive data simultaneously. This is
* implemented by using the `fork` function call so that in the server the child
* process can receive data and parent process can send data, and in the client
* the child process can send data and the parent process can receive data. It
* runs an infinite loop and can send and receive messages indefinitely until
* the user exits the loop. In this way, the Full Duplex Form of communication
* can be represented using the TCP server-client model & socket programming
*/
#ifdef _WIN32 #ifdef _WIN32
#define bzero(b, len) \ #define bzero(b, len) (memset((b), '\0', (len)), (void)0)
(memset((b), '\0', (len)), (void)0) /**< BSD name not in windows */
#define pid_t int #define pid_t int
#define close _close #define close _close
#include <Ws2tcpip.h> #include <Ws2tcpip.h>
#include <io.h> #include <io.h>
#include <windows.h> #include <windows.h>
#include <winsock2.h> #include <winsock2.h>
#include "fork.h" #include "fork.h"
#define sleep(a) Sleep(a * 1000) #define sleep(a) Sleep(a * 1000)
#else #else
#include <arpa/inet.h> /// For the type in_addr_t and in_port_t #include <arpa/inet.h>
#include <netdb.h> /// For structures returned by the network database library - formatted internet addresses and port numbers #include <netdb.h>
#include <netinet/in.h> /// For in_addr and sockaddr_in structures #include <netinet/in.h>
#include <sys/socket.h> /// For macro definitions related to the creation of sockets #include <sys/socket.h>
#include <sys/types.h> /// For definitions to allow for the porting of BSD programs #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#endif #endif
#include <stdint.h> /// For specific bit size values of variables #include <stdint.h>
#include <stdio.h> /// Variable types, several macros, and various functions for performing input and output #include <stdio.h>
#include <stdlib.h> /// Variable types, several macros, and various functions for performing general functions #include <stdlib.h>
#include <string.h> /// Various functions for manipulating arrays of characters #include <string.h>
#define PORT 10000 /// Define port over which communication will take place #define PORT 10000
/**
* @brief Utility function used to print an error message to `stderr`.
* It prints `str` and an implementation-defined error
* message corresponding to the global variable `errno`.
* @returns void
*/
void error() void error()
{ {
perror("Socket Creation Failed"); perror("Socket Creation Failed");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/**
* @brief Main function
* @returns 0 on exit
*/
int main() int main()
{ {
/** Variable Declarations */ uint32_t sockfd;
uint32_t char sendbuff[1024], recvbuff[1024];
sockfd; ///< socket descriptors - Like file handles but for sockets
char sendbuff[1024],
recvbuff[1024]; ///< character arrays to read and store string data
/// for communication
struct sockaddr_in struct sockaddr_in server_addr;
server_addr; ///< basic structures for all syscalls and functions that
/// deal with internet addresses. Structures for handling
/// internet addresses
/**
* The TCP socket is created using the socket function.
*
* AF_INET (Family) - it is an address family that is used to designate the
* type of addresses that your socket can communicate with
*
* SOCK_STREAM (Type) - Indicates TCP Connection - A stream socket provides
* for the bidirectional, reliable, sequenced, and unduplicated flow of data
* without record boundaries. Aside from the bidirectionality of data flow,
* a pair of connected stream sockets provides an interface nearly identical
* to pipes.
*
* 0 (Protocol) - Specifies a particular protocol to be used with the
* socket. Specifying a protocol of 0 causes socket() to use an unspecified
* default protocol appropriate for the requested socket type.
*/
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{ {
error(); error();
} }
/**
* Server Address Information
*
* The bzero() function erases the data in the n bytes of the memory
* starting at the location pointed to, by writing zeros (bytes
* containing '\0') to that area.
*
* We bind the server_addr to the internet address and port number thus
* giving our socket an identity with an address and port where it can
* listen for connections
*
* htons - The htons() function translates a short integer from host byte
* order to network byte order
*
* htonl - The htonl() function translates a long integer from host byte
* order to network byte order
*
* These functions are necessary so that the binding of address and port
* takes place with data in the correct format
*/
bzero(&server_addr, sizeof(server_addr)); bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET; server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT); server_addr.sin_port = htons(PORT);
@ -121,41 +49,14 @@ int main()
printf("Client is running...\n"); printf("Client is running...\n");
/**
* Connects the client to the server address using the socket descriptor
* This enables the two to communicate and exchange data
*/
connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)); connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
printf("Client is connected...\n"); printf("Client is connected...\n");
/**
* Communication between client and server
*
* The bzero() function erases the data in the n bytes of the memory
* starting at the location pointed to, by writing zeros (bytes
* containing '\0') to that area. The variables are emptied and then
* ready for use
*
* The fork function call is used to create a child and parent process
* which run and execute code simultaneously
*
* The child process is used to send data and after doing so
* sleeps for 5 seconds to wait for the parent to receive data
*
* The parent process is used to receive data and after doing so
* sleeps for 5 seconds to wait for the child to send data
*
* The server and client can communicate indefinitely till one of them
* exits the connection
*
* Since the exchange of information between the server and client takes
* place simultaneously this represents FULL DUPLEX COMMUNICATION
*/
pid_t pid; pid_t pid;
pid = fork(); pid = fork();
if (pid == 0) /// Value of 0 is for child process if (pid == 0)
{ {
while (1) while (1)
{ {
@ -165,10 +66,9 @@ int main()
send(sockfd, sendbuff, strlen(sendbuff) + 1, 0); send(sockfd, sendbuff, strlen(sendbuff) + 1, 0);
printf("\nMessage sent!\n"); printf("\nMessage sent!\n");
sleep(5); sleep(5);
// break;
} }
} }
else /// Parent Process else
{ {
while (1) while (1)
{ {
@ -176,11 +76,9 @@ int main()
recv(sockfd, recvbuff, sizeof(recvbuff), 0); recv(sockfd, recvbuff, sizeof(recvbuff), 0);
printf("\nSERVER: %s\n", recvbuff); printf("\nSERVER: %s\n", recvbuff);
sleep(5); sleep(5);
// break;
} }
} }
/// Close Socket
close(sockfd); close(sockfd);
printf("Client is offline...\n"); printf("Client is offline...\n");
return 0; return 0;

View File

@ -1,121 +1,49 @@
/**
* @file
* @author [NVombat](https://github.com/NVombat)
* @brief Server-side implementation of [TCP Full Duplex
* Communication](http://www.tcpipguide.com/free/t_SimplexFullDuplexandHalfDuplexOperation.htm)
* @see tcp_full_duplex_client.c
*
* @details
* The algorithm is based on the simple TCP client and server model. However,
* instead of the server only sending and the client only receiving data,
* The server and client can both send and receive data simultaneously. This is
* implemented by using the `fork` function call so that in the server the child
* process can receive data and parent process can send data, and in the client
* the child process can send data and the parent process can receive data. It
* runs an infinite loop and can send and receive messages indefinitely until
* the user exits the loop. In this way, the Full Duplex Form of communication
* can be represented using the TCP server-client model & socket programming
*/
#ifdef _WIN32 #ifdef _WIN32
#define bzero(b, len) \ #define bzero(b, len) (memset((b), '\0', (len)), (void)0)
(memset((b), '\0', (len)), (void)0) /**< BSD name not in windows */
#define pid_t int #define pid_t int
#define close _close #define close _close
#include <Ws2tcpip.h> #include <Ws2tcpip.h>
#include <io.h> #include <io.h>
#include <windows.h> #include <windows.h>
#include <winsock2.h> #include <winsock2.h>
#include "fork.h" #include "fork.h"
#define sleep(a) Sleep(a * 1000) #define sleep(a) Sleep(a * 1000)
#else #else
#include <arpa/inet.h> /// For the type in_addr_t and in_port_t #include <arpa/inet.h>
#include <netdb.h> /// For structures returned by the network database library - formatted internet addresses and port numbers #include <netdb.h>
#include <netinet/in.h> /// For in_addr and sockaddr_in structures #include <netinet/in.h>
#include <sys/socket.h> /// For macro definitions related to the creation of sockets #include <sys/socket.h>
#include <sys/types.h> /// For definitions to allow for the porting of BSD programs #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#endif #endif
#include <stdint.h> /// For specific bit size values of variables #include <stdint.h>
#include <stdio.h> /// Variable types, several macros, and various functions for performing input and output #include <stdio.h>
#include <stdlib.h> /// Variable types, several macros, and various functions for performing general functions #include <stdlib.h>
#include <string.h> /// Various functions for manipulating arrays of characters #include <string.h>
#define PORT 10000 /// Define port over which communication will take place #define PORT 10000
/**
* @brief Utility function used to print an error message to `stderr`.
* It prints `str` and an implementation-defined error
* message corresponding to the global variable `errno`.
* @returns void
*/
void error() void error()
{ {
perror("Socket Creation Failed"); perror("Socket Creation Failed");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/**
* @brief Main function
* @returns 0 on exit
*/
int main() int main()
{ {
/** Variable Declarations */ uint32_t sockfd, conn;
uint32_t sockfd, char recvbuff[1024], sendbuff[1024];
conn; ///< socket descriptors - Like file handles but for sockets
char recvbuff[1024],
sendbuff[1024]; ///< character arrays to read and store string data
/// for communication
struct sockaddr_in server_addr, struct sockaddr_in server_addr, client_addr;
client_addr; ///< basic structures for all syscalls and functions that
/// deal with internet addresses. Structures for handling socklen_t ClientLen;
/// internet addresses
socklen_t ClientLen; /// size of address
/**
* The TCP socket is created using the socket function
*
* AF_INET (Family) - it is an address family that is used to designate the
* type of addresses that your socket can communicate with
*
* SOCK_STREAM (Type) - Indicates TCP Connection - A stream socket provides
* for the bidirectional, reliable, sequenced, and unduplicated flow of data
* without record boundaries. Aside from the bidirectionality of data flow,
* a pair of connected stream sockets provides an interface nearly identical
* to pipes
*
* 0 (Protocol) - Specifies a particular protocol to be used with the
* socket. Specifying a protocol of 0 causes socket() to use an unspecified
* default protocol appropriate for the requested socket type
*/
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{ {
error(); ///< Error if the socket descriptor has a value lower than 0 - error();
/// socket wasnt created
} }
/**
* Server Address Information
*
* The bzero() function erases the data in the n bytes of the memory
* starting at the location pointed to, by writing zeros (bytes
* containing '\0') to that area
*
* We bind the server_addr to the internet address and port number thus
* giving our socket an identity with an address and port where it can
* listen for connections
*
* htons - The htons() function translates a short integer from host byte
* order to network byte order
*
* htonl - The htonl() function translates a long integer from host byte
* order to network byte order
*
* These functions are necessary so that the binding of address and port
* takes place with data in the correct format
*/
bzero(&server_addr, sizeof(server_addr)); bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET; server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT); server_addr.sin_port = htons(PORT);
@ -123,68 +51,30 @@ int main()
printf("Server is running...\n"); printf("Server is running...\n");
/**
* This binds the socket descriptor to the server thus enabling the server
* to listen for connections and communicate with other clients
*/
if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
{ {
error(); /// If binding is unsuccessful error();
} }
/**
* This is to listen for clients or connections made to the server
*
* The limit is currently at 5 but can be increased to listen for
* more connections
*
* It listens to connections through the socket descriptor
*/
listen(sockfd, 5); listen(sockfd, 5);
printf("Server is listening...\n"); printf("Server is listening...\n");
/**
* When a connection is found, a socket is created and connection is
* accepted and established through the socket descriptor
*/
conn = accept(sockfd, (struct sockaddr *)NULL, NULL); conn = accept(sockfd, (struct sockaddr *)NULL, NULL);
printf("Server is connected...\n"); printf("Server is connected...\n");
/**
* Communication between client and server
*
* The bzero() function erases the data in the n bytes of the memory
* starting at the location pointed to, by writing zeros (bytes
* containing '\0') to that area. The variables are emptied and then
* ready for use
*
* The fork function call is used to create a child and parent process
* which run and execute code simultaneously
*
* The child process is used to receive data and after doing so
* sleeps for 5 seconds to wait for the parent to send data
*
* The parent process is used to send data and after doing so
* sleeps for 5 seconds to wait for the child to receive data
*
* The server and client can communicate indefinitely till one of them
* exits the connection
*
* Since the exchange of information between the server and client takes
* place simultaneously this represents FULL DUPLEX COMMUNICATION
*/
pid_t pid; pid_t pid;
#ifdef _WIN32 #ifdef _WIN32
#ifdef FORK_WINDOWS #ifdef FORK_WINDOWS
pid = fork(); pid = fork();
#endif #endif
#else #else
pid = fork(); pid = fork();
#endif #endif
if (pid == 0) /// Value of 0 is for child process if (pid == 0)
{ {
while (1) while (1)
{ {
@ -192,10 +82,9 @@ int main()
recv(conn, recvbuff, sizeof(recvbuff), 0); recv(conn, recvbuff, sizeof(recvbuff), 0);
printf("\nCLIENT : %s\n", recvbuff); printf("\nCLIENT : %s\n", recvbuff);
sleep(5); sleep(5);
// break;
} }
} }
else /// Parent process else
{ {
while (1) while (1)
{ {
@ -205,11 +94,9 @@ int main()
send(conn, sendbuff, strlen(sendbuff) + 1, 0); send(conn, sendbuff, strlen(sendbuff) + 1, 0);
printf("\nMessage Sent!\n"); printf("\nMessage Sent!\n");
sleep(5); sleep(5);
// break;
} }
} }
/// Close socket
close(sockfd); close(sockfd);
printf("Server is offline...\n"); printf("Server is offline...\n");
return 0; return 0;

View File

@ -1,111 +1,40 @@
/**
* @file
* @author [Nikhill Vombatkere](https://github.com/NVombat)
* @brief Client-side implementation of [TCP Half Duplex
* Communication](http://www.tcpipguide.com/free/t_SimplexFullDuplexandHalfDuplexOperation.htm)
* @see tcp_half_duplex_server.c
*
* @details
* The algorithm is based on the simple TCP client and server model. However,
* instead of the server only sending and the client only receiving data,
* the server and client can both send data but only one at a time. This is
* implemented by using a particular ordering of the `send()` and `recv()`
* functions. When one of the clients or servers is sending, the other can only
* receive and vice-versa. In this way, the Half Duplex Form of communication
* can be represented using the TCP server-client model & socket programming
*/
#ifdef _WIN32 #ifdef _WIN32
#define bzero(b, len) \ #define bzero(b, len) (memset((b), '\0', (len)), (void)0)
(memset((b), '\0', (len)), (void)0) /**< BSD name not in windows */
#define close _close #define close _close
#include <Ws2tcpip.h> #include <Ws2tcpip.h>
#include <io.h> #include <io.h>
#include <winsock2.h> #include <winsock2.h>
#else #else
#include <netdb.h> /// For structures returned by the network database library - formatted internet addresses and port numbers #include <netdb.h>
#include <sys/socket.h> /// For macro definitions related to the creation of sockets #include <sys/socket.h>
#include <sys/types.h> /// For definitions to allow for the porting of BSD programs #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#endif #endif
// #include <netinet/in.h> /// For in_addr and sockaddr_in structures #include <stdint.h>
#include <stdint.h> /// For specific bit size values of variables #include <stdio.h>
#include <stdio.h> /// Variable types, several macros, and various functions for performing input and output #include <stdlib.h>
#include <stdlib.h> /// Variable types, several macros, and various functions for performing general functions #include <string.h>
#include <string.h> /// Various functions for manipulating arrays of characters
#define PORT 8100 /// Define port over which communication will take place #define PORT 8100
/**
* @brief Utility function used to print an error message to `stderr`.
* It prints `str` and an implementation-defined error
* message corresponding to the global variable `errno`.
* @returns void
*/
void error() void error()
{ {
perror("Socket Creation Failed"); perror("Socket Creation Failed");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/**
* @brief Main function
* @returns 0 on exit
*/
int main() int main()
{ {
/** Variable Declarations */ uint32_t sockfd;
uint32_t struct sockaddr_in server_addr;
sockfd; ///< socket descriptors - Like file handles but for sockets
struct sockaddr_in char serverResponse[10000], clientResponse[10000];
server_addr; ///< basic structures for all syscalls and functions that
/// deal with internet addresses. Structures for handling
/// internet addresses
char serverResponse[10000],
clientResponse[10000]; ///< Character arrays to read and store string
/// data for communication
/**
* The TCP socket is created using the socket function.
*
* AF_INET (Family) - it is an address family that is used to designate the
* type of addresses that your socket can communicate with
*
* SOCK_STREAM (Type) - Indicates TCP Connection - A stream socket provides
* for the bidirectional, reliable, sequenced, and unduplicated flow of data
* without record boundaries. Aside from the bidirectionality of data flow,
* a pair of connected stream sockets provides an interface nearly identical
* to pipes.
*
* 0 (Protocol) - Specifies a particular protocol to be used with the
* socket. Specifying a protocol of 0 causes socket() to use an unspecified
* default protocol appropriate for the requested socket type.
*/
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{ {
error(); error();
} }
/**
* Server Address Information
*
* The bzero() function erases the data in the n bytes of the memory
* starting at the location pointed to, by writing zeros (bytes
* containing '\0') to that area.
*
* We bind the server_addr to the internet address and port number thus
* giving our socket an identity with an address and port where it can
* listen for connections
*
* htons - The htons() function translates a short integer from host byte
* order to network byte order
*
* htonl - The htonl() function translates a long integer from host byte
* order to network byte order
*
* These functions are necessary so that the binding of address and port
* takes place with data in the correct format
*/
bzero(&server_addr, sizeof(server_addr)); bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET; server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT); server_addr.sin_port = htons(PORT);
@ -113,49 +42,23 @@ int main()
printf("Client is running...\n"); printf("Client is running...\n");
/**
* Connects the client to the server address using the socket descriptor
* This enables the two to communicate and exchange data
*/
connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)); connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
printf("Client is connected...\n"); printf("Client is connected...\n");
/**
* Communication between client and server
*
* The bzero() function erases the data in the n bytes of the memory
* starting at the location pointed to, by writing zeros (bytes
* containing '\0') to that area. The variables are emptied and then
* ready for use
*
* First the CLIENT receives the servers message and displays it (recv())
*
* The CLIENT is then prompted to type in a message and send it to the
* server. (send())
*
* The server and client can communicate till one of them exits the
* connection
*
* Since the exchange of information between the server and client take
* place one at a time this represents HALF DUPLEX COMMUNICATION
*/
while (1) while (1)
{ {
bzero(&serverResponse, sizeof(serverResponse)); bzero(&serverResponse, sizeof(serverResponse));
bzero(&clientResponse, sizeof(clientResponse)); bzero(&clientResponse, sizeof(clientResponse));
/// Receive Message
recv(sockfd, serverResponse, sizeof(serverResponse), 0); recv(sockfd, serverResponse, sizeof(serverResponse), 0);
printf("\nServer message: %s \n", serverResponse); printf("\nServer message: %s \n", serverResponse);
/// Send Message
printf("\nEnter message here: "); printf("\nEnter message here: ");
fgets(clientResponse, 10000, stdin); fgets(clientResponse, 10000, stdin);
send(sockfd, clientResponse, strlen(clientResponse) + 1, 0); send(sockfd, clientResponse, strlen(clientResponse) + 1, 0);
} }
/// Close Socket
close(sockfd); close(sockfd);
printf("Client is offline...\n"); printf("Client is offline...\n");
return 0; return 0;

View File

@ -1,185 +1,73 @@
/**
* @file
* @author [NVombat](https://github.com/NVombat)
* @brief Server-side implementation of [TCP Half Duplex
* Communication](http://www.tcpipguide.com/free/t_SimplexFullDuplexandHalfDuplexOperation.htm)
* @see tcp_half_duplex_server.c
*
* @details
* The algorithm is based on the simple TCP client and server model. However,
* instead of the server only sending and the client only receiving data,
* The server and client can both send data but only one at a time. This is
* implemented by using a particular ordering of the `send()` and `recv()`
* functions. When one of the clients or servers is sending, the other can only
* receive and vice-versa. In this way, the Half Duplex Form of communication
* can be represented using the TCP server-client model & socket programming
*/
#ifdef _WIN32 #ifdef _WIN32
#define bzero(b, len) \ #define bzero(b, len) (memset((b), '\0', (len)), (void)0)
(memset((b), '\0', (len)), (void)0) /**< BSD name not in windows */
#define close _close #define close _close
#include <Ws2tcpip.h> #include <Ws2tcpip.h>
#include <io.h> #include <io.h>
#include <winsock2.h> #include <winsock2.h>
#else #else
#include <netdb.h> /// For structures returned by the network database library - formatted internet addresses and port numbers #include <netdb.h>
#include <sys/socket.h> /// For macro definitions related to the creation of sockets #include <sys/socket.h>
#include <sys/types.h> /// For definitions to allow for the porting of BSD programs #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#endif #endif
// #include <netinet/in.h> /// For in_addr and sockaddr_in structures #include <stdint.h>
#include <stdint.h> /// For specific bit size values of variables #include <stdio.h>
#include <stdio.h> /// Variable types, several macros, and various functions for performing input and output #include <stdlib.h>
#include <stdlib.h> /// Variable types, several macros, and various functions for performing general functions #include <string.h>
#include <string.h> /// Various functions for manipulating arrays of characters
#define PORT 8100 /// Define port over which communication will take place #define PORT 8100
/**
* @brief Utility function used to print an error message to `stderr`.
* It prints `str` and an implementation-defined error
* message corresponding to the global variable `errno`.
* @returns void
*/
void error() void error()
{ {
perror("Socket Creation Failed"); perror("Socket Creation Failed");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/**
* @brief Main function
* @returns 0 on exit
*/
int main() int main()
{ {
/** Variable Declarations */ uint32_t sockfd, conn;
uint32_t sockfd, char server_msg[10000], client_msg[10000];
conn; ///< socket descriptors - Like file handles but for sockets
char server_msg[10000], struct sockaddr_in server_addr, client_addr;
client_msg[10000]; ///< character arrays to read and store string data
/// for communication
struct sockaddr_in server_addr,
client_addr; ///< asic structures for all syscalls and functions that
/// deal with internet addresses. Structures for handling
/// internet addresses
/**
* The TCP socket is created using the socket function
*
* AF_INET (Family) - it is an address family that is used to designate the
* type of addresses that your socket can communicate with
*
* SOCK_STREAM (Type) - Indicates TCP Connection - A stream socket provides
* for the bidirectional, reliable, sequenced, and unduplicated flow of data
* without record boundaries. Aside from the bidirectionality of data flow,
* a pair of connected stream sockets provides an interface nearly identical
* to pipes
*
* 0 (Protocol) - Specifies a particular protocol to be used with the
* socket. Specifying a protocol of 0 causes socket() to use an unspecified
* default protocol appropriate for the requested socket type
*/
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{ {
error(); ///< Error if the socket descriptor has a value lower than 0 - error();
/// socket wasnt created
} }
/**
* Server Address Information
*
* The bzero() function erases the data in the n bytes of the memory
* starting at the location pointed to, by writing zeros (bytes
* containing '\0') to that area
*
* We bind the server_addr to the internet address and port number thus
* giving our socket an identity with an address and port where it can
* listen for connections
*
* htons - The htons() function translates a short integer from host byte
* order to network byte order
*
* htonl - The htonl() function translates a long integer from host byte
* order to network byte order
*
* These functions are necessary so that the binding of address and port
* takes place with data in the correct format
*/
bzero(&server_addr, sizeof(server_addr)); bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET; /// Domain/Family to be used server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT); /// Port to be used server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
printf("Server is running...\n"); printf("Server is running...\n");
/**
* This binds the socket descriptor to the server thus enabling the server
* to listen for connections and communicate with other clients
*/
if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
{ {
error(); /// If binding is unsuccessful error();
} }
/**
* This is to listen for clients or connections made to the server
*
* The limit is currently at 5 but can be increased to listen for
* more connections
*
* It listens to connections through the socket descriptor
*/
listen(sockfd, 5); listen(sockfd, 5);
printf("Server is listening...\n"); printf("Server is listening...\n");
/**
* When a connection is found, a socket is created and connection is
* accepted and established through the socket descriptor
*/
conn = accept(sockfd, (struct sockaddr *)NULL, NULL); conn = accept(sockfd, (struct sockaddr *)NULL, NULL);
printf("Server is connected...\n"); printf("Server is connected...\n");
/**
* Communication between client and server
*
* The bzero() function erases the data in the n bytes of the memory
* starting at the location pointed to, by writing zeros (bytes
* containing '\0') to that area. The variables are emptied and then
* ready for use
*
* First the SERVER is prompted to type a message which is read from
* stdin and then sent over the connection that was established - the socket
* - to be received by the client (send())
*
* The SERVER then waits for the client to reply. It then receives the reply
* in the string variable and displays it (recv())
*
* The server and client can communicate till one of them exits the
* connection
*
* Since the exchange of information between the server and client take
* place one at a time this represents HALF DUPLEX COMMUNICATION
*/
while (1) while (1)
{ {
bzero(&server_msg, sizeof(server_msg)); bzero(&server_msg, sizeof(server_msg));
bzero(&client_msg, sizeof(client_msg)); bzero(&client_msg, sizeof(client_msg));
/// Send message
printf("\nEnter message here: "); printf("\nEnter message here: ");
fgets(server_msg, 10000, stdin); fgets(server_msg, 10000, stdin);
send(conn, server_msg, strlen(server_msg) + 1, 0); send(conn, server_msg, strlen(server_msg) + 1, 0);
/// Receive Message
recv(conn, client_msg, sizeof(client_msg), 0); recv(conn, client_msg, sizeof(client_msg), 0);
printf("\nClient Message: %s\n", client_msg); printf("\nClient Message: %s\n", client_msg);
} }
/// Close socket
close(sockfd); close(sockfd);
printf("Server is offline...\n"); printf("Server is offline...\n");
return 0; return 0;

View File

@ -1,16 +1,9 @@
/** #ifdef _WIN32
* @file #define _WINSOCK_DEPRECATED_NO_WARNINGS
* @author [TheShubham99](https://github.com/TheShubham99)
* @author [Krishna Vedala](https://github.com/kvedala)
* @brief Client side implementation of UDP client-server model
* @see client_server/udp_server.c
*/
#ifdef _WIN32 // if compiling for Windows
#define _WINSOCK_DEPRECATED_NO_WARNINGS // will make the code invalid for next
// MSVC compiler versions
#include <winsock2.h> #include <winsock2.h>
#define close closesocket /**< map BSD name to Winsock */ #define close closesocket
#else // if not windows platform #else
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
#include <netinet/in.h> #include <netinet/in.h>
@ -23,19 +16,16 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define PORT 8080 /**< port number to connect to */ #define PORT 8080
#define MAXLINE 1024 /**< maximum characters per line */ #define MAXLINE 1024
#ifdef _WIN32 #ifdef _WIN32
/** Cleanup function will be automatically called on program exit */
void cleanup() { WSACleanup(); } void cleanup() { WSACleanup(); }
#endif #endif
/** Driver code */
int main() int main()
{ {
#ifdef _WIN32 #ifdef _WIN32
// when using winsock2.h, startup required
WSADATA wsData; WSADATA wsData;
if (WSAStartup(MAKEWORD(2, 2), &wsData) != 0) if (WSAStartup(MAKEWORD(2, 2), &wsData) != 0)
{ {
@ -43,7 +33,7 @@ int main()
return 0; return 0;
} }
atexit(cleanup); // register at-exit function atexit(cleanup);
#endif #endif
int sockfd; int sockfd;
@ -51,7 +41,6 @@ int main()
char *hello = "Hello from client"; char *hello = "Hello from client";
struct sockaddr_in servaddr; struct sockaddr_in servaddr;
// Creating socket file descriptor
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{ {
perror("socket creation failed"); perror("socket creation failed");
@ -60,7 +49,6 @@ int main()
memset(&servaddr, 0, sizeof(servaddr)); memset(&servaddr, 0, sizeof(servaddr));
// Filling server information
servaddr.sin_family = AF_INET; servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT); servaddr.sin_port = htons(PORT);
servaddr.sin_addr.s_addr = INADDR_ANY; servaddr.sin_addr.s_addr = INADDR_ANY;
@ -72,7 +60,7 @@ int main()
(const struct sockaddr *)&servaddr, sizeof(servaddr)); (const struct sockaddr *)&servaddr, sizeof(servaddr));
printf("Hello message sent.\n"); printf("Hello message sent.\n");
n = recvfrom(sockfd, (char *)buffer, MAXLINE, MSG_WAITALL, n = recvfrom(sockfd, (char *)buffer, MAXLINE, 0,
(struct sockaddr *)&servaddr, &len); (struct sockaddr *)&servaddr, &len);
buffer[n] = '\0'; buffer[n] = '\0';
printf("Server : %s\n", buffer); printf("Server : %s\n", buffer);

View File

@ -1,16 +1,8 @@
/** #ifdef _WIN32
* @file #define _WINSOCK_DEPRECATED_NO_WARNINGS
* @author [TheShubham99](https://github.com/TheShubham99) #define close closesocket
* @author [Krishna Vedala](https://github.com/kvedala)
* @brief Server side implementation of UDP client-server model
* @see client_server/udp_client.c
*/
#ifdef _WIN32 // if compiling for Windows
#define _WINSOCK_DEPRECATED_NO_WARNINGS // will make the code invalid for next
// MSVC compiler versions
#define close closesocket /**< map BSD name to Winsock */
#include <winsock2.h> #include <winsock2.h>
#else // if not windows platform #else
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
#include <netinet/in.h> #include <netinet/in.h>
@ -23,19 +15,17 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define PORT 8080 /**< port number to connect to */ #define PORT 8080
#define MAXLINE 1024 /**< maximum characters per line */ #define MAXLINE 1024
#ifdef _WIN32 #ifdef _WIN32
/** Cleanup function will be automatically called on program exit */
void cleanup() { WSACleanup(); } void cleanup() { WSACleanup(); }
#endif #endif
/** Driver code */
int main() int main()
{ {
#ifdef _WIN32 #ifdef _WIN32
// when using winsock2.h, startup required
WSADATA wsData; WSADATA wsData;
if (WSAStartup(MAKEWORD(2, 2), &wsData) != 0) if (WSAStartup(MAKEWORD(2, 2), &wsData) != 0)
{ {
@ -43,7 +33,7 @@ int main()
return 0; return 0;
} }
atexit(cleanup); // register at-exit function atexit(cleanup);
#endif #endif
int sockfd; int sockfd;
@ -51,7 +41,6 @@ int main()
char *hello = "Hello from server"; char *hello = "Hello from server";
struct sockaddr_in servaddr, cliaddr; struct sockaddr_in servaddr, cliaddr;
// Creating socket file descriptor
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{ {
perror("socket creation failed"); perror("socket creation failed");
@ -61,12 +50,10 @@ int main()
memset(&servaddr, 0, sizeof(servaddr)); memset(&servaddr, 0, sizeof(servaddr));
memset(&cliaddr, 0, sizeof(cliaddr)); memset(&cliaddr, 0, sizeof(cliaddr));
// Filling server information servaddr.sin_family = AF_INET;
servaddr.sin_family = AF_INET; // IPv4
servaddr.sin_addr.s_addr = INADDR_ANY; servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(PORT); servaddr.sin_port = htons(PORT);
// Bind the socket with the server address
if (bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) if (bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
{ {
perror("bind failed"); perror("bind failed");
@ -75,7 +62,7 @@ int main()
unsigned int len; unsigned int len;
int n; int n;
n = recvfrom(sockfd, (char *)buffer, MAXLINE, MSG_WAITALL, n = recvfrom(sockfd, (char *)buffer, MAXLINE, 0,
(struct sockaddr *)&cliaddr, &len); (struct sockaddr *)&cliaddr, &len);
buffer[n] = '\0'; buffer[n] = '\0';
printf("Client : %s\n", buffer); printf("Client : %s\n", buffer);