mirror of
https://github.com/Hizenberg469/Inter-Process-Communication-IPC-.git
synced 2026-04-20 02:12:25 +03:00
Unix Domain Socket
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
*vsidx
|
||||||
|
*.opendb
|
||||||
|
.vs
|
||||||
|
out
|
||||||
24
AF_UNIX/CMakeLists.txt
Normal file
24
AF_UNIX/CMakeLists.txt
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# CMakeList.txt : CMake project for AF_UNIX, include source and define
|
||||||
|
# project specific logic here.
|
||||||
|
#
|
||||||
|
cmake_minimum_required (VERSION 3.8)
|
||||||
|
|
||||||
|
# Enable Hot Reload for MSVC compilers if supported.
|
||||||
|
if (POLICY CMP0141)
|
||||||
|
cmake_policy(SET CMP0141 NEW)
|
||||||
|
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
project ( AF_UNIX VERSION 1.0.0 LANGUAGES C CXX)
|
||||||
|
|
||||||
|
set(CMAKE_C_STANDARD 17)
|
||||||
|
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_C_EXTENSIONS OFF)
|
||||||
|
|
||||||
|
# Add source to this project's executable.
|
||||||
|
add_executable (server "server.c")
|
||||||
|
add_executable (client "client.c")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: Add tests and install targets if needed.
|
||||||
101
AF_UNIX/CMakePresets.json
Normal file
101
AF_UNIX/CMakePresets.json
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"configurePresets": [
|
||||||
|
{
|
||||||
|
"name": "windows-base",
|
||||||
|
"hidden": true,
|
||||||
|
"generator": "Ninja",
|
||||||
|
"binaryDir": "${sourceDir}/out/build/${presetName}",
|
||||||
|
"installDir": "${sourceDir}/out/install/${presetName}",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_C_COMPILER": "cl.exe",
|
||||||
|
"CMAKE_CXX_COMPILER": "cl.exe"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"type": "equals",
|
||||||
|
"lhs": "${hostSystemName}",
|
||||||
|
"rhs": "Windows"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "x64-debug",
|
||||||
|
"displayName": "x64 Debug",
|
||||||
|
"inherits": "windows-base",
|
||||||
|
"architecture": {
|
||||||
|
"value": "x64",
|
||||||
|
"strategy": "external"
|
||||||
|
},
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_BUILD_TYPE": "Debug"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "x64-release",
|
||||||
|
"displayName": "x64 Release",
|
||||||
|
"inherits": "x64-debug",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_BUILD_TYPE": "Release"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "x86-debug",
|
||||||
|
"displayName": "x86 Debug",
|
||||||
|
"inherits": "windows-base",
|
||||||
|
"architecture": {
|
||||||
|
"value": "x86",
|
||||||
|
"strategy": "external"
|
||||||
|
},
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_BUILD_TYPE": "Debug"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "x86-release",
|
||||||
|
"displayName": "x86 Release",
|
||||||
|
"inherits": "x86-debug",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_BUILD_TYPE": "Release"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "linux-debug",
|
||||||
|
"displayName": "Linux Debug",
|
||||||
|
"generator": "Ninja",
|
||||||
|
"binaryDir": "${sourceDir}/out/build/${presetName}",
|
||||||
|
"installDir": "${sourceDir}/out/install/${presetName}",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_BUILD_TYPE": "Debug"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"type": "equals",
|
||||||
|
"lhs": "${hostSystemName}",
|
||||||
|
"rhs": "Linux"
|
||||||
|
},
|
||||||
|
"vendor": {
|
||||||
|
"microsoft.com/VisualStudioRemoteSettings/CMake/1.0": {
|
||||||
|
"sourceDir": "$env{HOME}/.vs/$ms{projectDirName}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "macos-debug",
|
||||||
|
"displayName": "macOS Debug",
|
||||||
|
"generator": "Ninja",
|
||||||
|
"binaryDir": "${sourceDir}/out/build/${presetName}",
|
||||||
|
"installDir": "${sourceDir}/out/install/${presetName}",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_BUILD_TYPE": "Debug"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"type": "equals",
|
||||||
|
"lhs": "${hostSystemName}",
|
||||||
|
"rhs": "Darwin"
|
||||||
|
},
|
||||||
|
"vendor": {
|
||||||
|
"microsoft.com/VisualStudioRemoteSettings/CMake/1.0": {
|
||||||
|
"sourceDir": "$env{HOME}/.vs/$ms{projectDirName}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
88
AF_UNIX/client.c
Normal file
88
AF_UNIX/client.c
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
#include <error.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define SOCKET_NAME "/tmp/DemoSocket"
|
||||||
|
#define BUFFER_SIZE 128
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char* argv[]) {
|
||||||
|
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
int i;
|
||||||
|
int ret;
|
||||||
|
int data_socket;
|
||||||
|
char buffer[BUFFER_SIZE];
|
||||||
|
|
||||||
|
/* Create data socket */
|
||||||
|
/* Client side don't have any concept of Master socket.
|
||||||
|
It directly use data socket to communicate with server. */
|
||||||
|
|
||||||
|
data_socket = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
|
||||||
|
if (data_socket == -1) {
|
||||||
|
perror("socket");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
For portability clear the whole structure, since some implementation
|
||||||
|
have additional (nonstandard) fields in the structure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
memset(&addr, 0, sizeof(struct sockaddr_un));
|
||||||
|
|
||||||
|
/* Connect socket to socket address. */
|
||||||
|
|
||||||
|
addr.sun_family = AF_UNIX;
|
||||||
|
strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) - 1);
|
||||||
|
|
||||||
|
ret = connect(data_socket, (const struct sockaddr*)&addr,
|
||||||
|
sizeof(struct sockaddr_un));
|
||||||
|
|
||||||
|
if (ret == -1) {
|
||||||
|
fprintf(stderr, "The server is down.\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send arguments */
|
||||||
|
do {
|
||||||
|
|
||||||
|
printf("Enter number to send to server :\n");
|
||||||
|
scanf("%d", &i);
|
||||||
|
ret = write(data_socket, &i, sizeof(int));
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("write");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("No of bytes sent = %d, data sent = %d\n", ret, i);
|
||||||
|
} while (i);
|
||||||
|
|
||||||
|
/* Request result */
|
||||||
|
|
||||||
|
memset(buffer, 0, BUFFER_SIZE);
|
||||||
|
strncpy(buffer, "RES", strlen("RES"));
|
||||||
|
buffer[strlen(buffer)] = '\0';
|
||||||
|
|
||||||
|
ret = read(data_socket, buffer, BUFFER_SIZE);
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("read");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure buffer is 0 - terminated */
|
||||||
|
|
||||||
|
buffer[BUFFER_SIZE - 1] = 0;
|
||||||
|
printf("%s\n", buffer);
|
||||||
|
|
||||||
|
/* Close socket */
|
||||||
|
|
||||||
|
close(data_socket);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
178
AF_UNIX/server.c
Normal file
178
AF_UNIX/server.c
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define SOCKET_NAME "/tmp/DemoSocket" /* Unique name of the socket */
|
||||||
|
#define BUFFER_SIZE 128 /* Size of the buffer which will be used by
|
||||||
|
for Communication. */
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char* argv[]) {
|
||||||
|
|
||||||
|
/* Structure provided by Unix library for using
|
||||||
|
it as an identifier for managing the socket */
|
||||||
|
|
||||||
|
struct sockaddr_un name;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
struct sockaddr_un {
|
||||||
|
|
||||||
|
/* This member describe what type of data it
|
||||||
|
will handle. Define the family of the
|
||||||
|
socket. Here, we are using UNIX DOMAIN socket
|
||||||
|
so AF_UNIX constant should be used for
|
||||||
|
classification. */
|
||||||
|
sa_family_t sun_family; /* AF_UNIX */
|
||||||
|
|
||||||
|
/* Hold the name of the socket with the path where it
|
||||||
|
is created. */
|
||||||
|
char sun_path[108]; /* pathname */
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
int connection_socket;
|
||||||
|
int data_socket;
|
||||||
|
int result;
|
||||||
|
int data;
|
||||||
|
char buffer[BUFFER_SIZE];
|
||||||
|
|
||||||
|
/* In case the program exited inadvertently on the last run,
|
||||||
|
remove the socket. */
|
||||||
|
|
||||||
|
|
||||||
|
unlink(SOCKET_NAME);
|
||||||
|
|
||||||
|
/* Create Master socket */
|
||||||
|
|
||||||
|
/* SOCK_DGRAM for Datagram based communication */
|
||||||
|
connection_socket = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
|
||||||
|
if (connection_socket == -1) {
|
||||||
|
|
||||||
|
perror("socket");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Master socket created\n");
|
||||||
|
|
||||||
|
/* initialize */
|
||||||
|
memset(&name, 0, sizeof(struct sockaddr_un));
|
||||||
|
|
||||||
|
/* Specify the socket Cridentials */
|
||||||
|
name.sun_family = AF_UNIX;
|
||||||
|
strncpy(name.sun_path, SOCKET_NAME, sizeof(name.sun_path) - 1);
|
||||||
|
|
||||||
|
/* Bind Socket to socket name. */
|
||||||
|
/* Purpose of bind() system call is that application() dictate the underlying
|
||||||
|
operating system the criteria of receiving the data. Here, bind() system call
|
||||||
|
is telling the OS that if sender process sends the data destined to socket
|
||||||
|
"tmp/DemoSocket", then such data needs to be delievered to this server process
|
||||||
|
( the server process ) */
|
||||||
|
|
||||||
|
ret = bind(connection_socket, (const struct sockaddr* )&name,
|
||||||
|
sizeof(struct sockaddr_un));
|
||||||
|
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("bind");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
printf("bind() call succeed\n");
|
||||||
|
|
||||||
|
/* Prepare for accepting connections. The backlog size is set to 20.
|
||||||
|
So, while one request is being processed other requests can be
|
||||||
|
waiting.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ret = listen(connection_socket, 20);
|
||||||
|
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("listen");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is the main loop for handling connections. */
|
||||||
|
/* All Server process usually runs 24 x 7. Good Servers should always up
|
||||||
|
running and should never go down. */
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
|
||||||
|
/* Wait for incoming connection. */
|
||||||
|
|
||||||
|
printf("Waiting on accept() sys call\n");
|
||||||
|
|
||||||
|
data_socket = accept(connection_socket, NULL, NULL);
|
||||||
|
|
||||||
|
if (data_socket == -1) {
|
||||||
|
perror("accept");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Connection accepted from client\n");
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
for (;;) {
|
||||||
|
|
||||||
|
/* Prepare the buffer to recv the data*/
|
||||||
|
memset(buffer, 0, BUFFER_SIZE);
|
||||||
|
|
||||||
|
/*Wait for next data packet. */
|
||||||
|
/* Server is blocked here. Waiting for the data to arrive from client
|
||||||
|
'read' is a blocking system call. */
|
||||||
|
printf("Waiting for data from the client\n");
|
||||||
|
|
||||||
|
ret = read(data_socket, buffer, BUFFER_SIZE);
|
||||||
|
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("read");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add received summand */
|
||||||
|
|
||||||
|
memcpy(&data, buffer, sizeof(int));
|
||||||
|
if (data == 0) break;
|
||||||
|
result += data;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send result. */
|
||||||
|
memset(buffer, 0, BUFFER_SIZE);
|
||||||
|
sprintf(buffer, "Result = %d", result);
|
||||||
|
|
||||||
|
|
||||||
|
printf("Sending final result back to client\n");
|
||||||
|
|
||||||
|
/* non-blockding system call */
|
||||||
|
ret = write(data_socket, buffer, BUFFER_SIZE);
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("write");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*close socket*/
|
||||||
|
close(data_socket);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*close the master socket*/
|
||||||
|
close(connection_socket);
|
||||||
|
printf("connection closed..\n");
|
||||||
|
|
||||||
|
/* Server should release resources before getting terminated.
|
||||||
|
Unlink the socket. */
|
||||||
|
|
||||||
|
unlink(SOCKET_NAME);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user