Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add: unix-socket chat #540

Open
wants to merge 2 commits into
base: ISochkov/main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#PhpStorm files
.idea
/vendor/
16 changes: 16 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "ivan/php_2023",
"type": "project",
"autoload": {
"psr-4": {
"App\\": "src/"
}
},
"authors": [
{
"name": "Iva-So",
"email": "[email protected]"
}
],
"require": {}
}
37 changes: 37 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# версия синтаксиса
version: '3'

# в этом блоке мы описываем контейнеры, которые будут запускаться
services:
#Контейнер с PHP-FPM, назовём его app
client:
# Если нет секции build, то система будет искать образ в репозиториях
build:
context: docker/fpm
dockerfile: Dockerfile
image: php-fpm # имя будущего образа
container_name: client # имя контейнера после запуска
volumes:
- .:/chat
# мы можем создать для контейнеров внутреннюю сеть
networks:
- app-network

#Контейнер с PHP-FPM, назовём его app
server:
# Если нет секции build, то система будет искать образ в репозиториях
build:
context: docker/fpm
dockerfile: Dockerfile
image: php-fpm # имя будущего образа
container_name: server # имя контейнера после запуска
volumes:
- .:/chat
# мы можем создать для контейнеров внутреннюю сеть
networks:
- app-network

#Docker Networks
networks:
app-network:
driver: bridge
23 changes: 23 additions & 0 deletions docker/fpm/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
FROM php:7.4-fpm

# ставим необходимые для нормальной работы модули
RUN apt-get update && apt-get install -y \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
libonig-dev \
libzip-dev \
libmemcached-dev \
libmcrypt-dev \
&& pecl install mcrypt-1.0.3 \
&& docker-php-ext-enable mcrypt \
&& docker-php-ext-install -j$(nproc) iconv mbstring mysqli pdo_mysql zip sockets\
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j$(nproc) gd \
&& pecl install memcached && \
docker-php-ext-enable memcached

# Install Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

WORKDIR /chat
63 changes: 63 additions & 0 deletions src/Client/Client.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

declare(strict_types=1);

namespace App\Client;

use Exception;

class Client
{
/**
* @throws Exception
*/
public function run(): void
{
if (!extension_loaded('sockets')) {
throw new Exception('The sockets extension is not loaded.');
}

$socket = socket_create(AF_UNIX, SOCK_DGRAM, 0);
if (!$socket) {
throw new Exception('Unable to create AF_UNIX socket');
}

$clientSideSock = dirname(__FILE__) . "/client.sock";
if (!socket_bind($socket, $clientSideSock)) {
throw new Exception("Unable to bind to $clientSideSock");
}

while (1) {
if (!socket_set_nonblock($socket)) {
throw new Exception('Unable to set nonblocking mode for socket');
}

$serverSideSock = dirname(__FILE__) . "/../Server/server.sock";

echo 'Enter your message: ';
fopen('php://stdin', 'r');
$msg = fread(STDIN, 1024);
$len = strlen($msg);

$bytesSent = socket_sendto($socket, $msg, $len, 0, $serverSideSock);
if ($bytesSent == -1) {
throw new Exception('An error occurred while sending to the socket');
} elseif ($bytesSent != $len) {
throw new Exception($bytesSent . ' bytes have been sent instead of the ' . $len . ' bytes expected');
}

if (!socket_set_block($socket)) {
throw new Exception('Unable to set blocking mode for socket');
}

$msg = '';
$from = '';

$bytesReceived = socket_recvfrom($socket, $msg, 65536, 0, $from);
if ($bytesReceived == -1) {
throw new Exception('An error occurred while receiving from the socket');
}
echo "Received: $msg";
}
}
}
14 changes: 14 additions & 0 deletions src/Client/app.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

require_once __DIR__ . '/../../vendor/autoload.php';

use App\Client\Client;

try {
$client = new Client();
$client->run();
} catch (Exception $e) {
echo $e->__toString();
}
59 changes: 59 additions & 0 deletions src/Server/Server.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

declare(strict_types=1);

namespace App\Server;

use Exception;

class Server
{
/**
* @throws Exception
*/
public function run(): void
{
if (!extension_loaded('sockets')) {
throw new Exception('The sockets extension is not loaded.');
}

$socket = socket_create(AF_UNIX, SOCK_DGRAM, 0);
if (!$socket) {
throw new Exception('Unable to create AF_UNIX socket');
}

$serverSideSock = dirname(__FILE__) . "/server.sock";
if (!socket_bind($socket, $serverSideSock)) {
throw new Exception("Unable to bind to $serverSideSock");
}

while (1) {
if (!socket_set_block($socket)) {
throw new Exception('Unable to set blocking mode for socket');
}

$msg = '';
$from = '';
echo "Ready to receive...\n";

$bytesReceived = socket_recvfrom($socket, $msg, 65536, 0, $from);
if ($bytesReceived == -1) {
throw new Exception('An error occurred while receiving from the socket');
}

echo "Received: $msg";

if (!socket_set_nonblock($socket)) {
throw new Exception('Unable to set nonblocking mode for socket');
}

$len = strlen($msg);
$bytesSent = socket_sendto($socket, $msg, $len, 0, $from);
if ($bytesSent == -1) {
throw new Exception('An error occurred while sending to the socket');
} elseif ($bytesSent != $len) {
throw new Exception($bytesSent . ' bytes have been sent instead of the ' . $len . ' bytes expected');
}
}
}
}
14 changes: 14 additions & 0 deletions src/Server/app.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

require_once(__DIR__ . '/../../vendor/autoload.php');

use App\Server\Server;

try {
$server = new Server();
$server->run();
} catch (Exception $e) {
echo $e->__toString();
}
Loading