mirror of
https://github.com/TheAlgorithms/C
synced 2024-11-22 05:21:49 +03:00
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:
parent
e5dad3fa8d
commit
60abb8fea7
14
.gitignore
vendored
14
.gitignore
vendored
@ -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/
|
||||||
|
@ -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,7 +13,6 @@
|
|||||||
#undef FALSE
|
#undef FALSE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
@ -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)
|
#define BOOLtobool(w) ((w != FALSE) ? true : false)
|
||||||
|
|
||||||
/* converts bool to BOOL */
|
|
||||||
#define booltoBOOL(w) ((w == true) ? TRUE : FALSE)
|
#define booltoBOOL(w) ((w == true) ? TRUE : FALSE)
|
||||||
|
|
||||||
#endif /* __BOOL_H__ */
|
#endif
|
||||||
/*--------------------------------------------------------------------------*/
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
/*--------------------------------------------------------------------------*/
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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,57 +51,19 @@ 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
|
||||||
@ -184,7 +74,7 @@ int main()
|
|||||||
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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user