initial commit
This commit is contained in:
@@ -0,0 +1,6 @@
|
|||||||
|
BasedOnStyle: Google
|
||||||
|
AllowShortFunctionsOnASingleLine: false
|
||||||
|
SpaceAfterCStyleCast: true
|
||||||
|
PointerBindsToType: false
|
||||||
|
DerivePointerBinding: false
|
||||||
|
IncludeBlocks: Preserve
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
build
|
||||||
|
*.o
|
||||||
|
sch
|
||||||
|
schc
|
||||||
|
.cache
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
cmake_minimum_required (VERSION 3.6)
|
||||||
|
project(sch LANGUAGES C)
|
||||||
|
|
||||||
|
set(CMAKE_C_STANDARD 23)
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
|
FILE(GLOB_RECURSE SOURCES src/main.c)
|
||||||
|
FILE(GLOB_RECURSE SOURCES_CLIENT src/client.c)
|
||||||
|
|
||||||
|
add_executable(
|
||||||
|
sch
|
||||||
|
${SOURCES}
|
||||||
|
)
|
||||||
|
add_executable(
|
||||||
|
schc
|
||||||
|
${SOURCES_CLIENT}
|
||||||
|
)
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
CC = gcc
|
||||||
|
CFLAGS = -Wall -g -std=gnu2x
|
||||||
|
LDFLAGS =
|
||||||
|
LIBS =
|
||||||
|
INCLUDES = -I./src/lib -I./src
|
||||||
|
SRCS = src/main.c
|
||||||
|
CSRCS = src/client.c
|
||||||
|
OBJS = src/main.o
|
||||||
|
COBJS = src/client.o
|
||||||
|
TARGET = sch
|
||||||
|
CTARGET = schc
|
||||||
|
CROSS_COMPILE =
|
||||||
|
|
||||||
|
all: $(TARGET) $(CTARGET)
|
||||||
|
|
||||||
|
$(TARGET): $(OBJS)
|
||||||
|
$(CROSS_COMPILE)$(CC) $(LDFLAGS) $^ -o $@ $(LIBS)
|
||||||
|
|
||||||
|
$(CTARGET): $(COBJS)
|
||||||
|
$(CROSS_COMPILE)$(CC) $(LDFLAGS) $^ -o $@ $(LIBS)
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CROSS_COMPILE)$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(OBJS) $(TARGET) $(CTARGET)
|
||||||
|
|
||||||
|
test: $(TARGET)
|
||||||
|
bash ./tests.sh
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
project('sch', 'c', default_options: ['cpp_std=c20'])
|
||||||
|
include_dirs = include_directories('src')
|
||||||
|
executable('sch', 'src/main.c', include_directories: include_dirs, install: true)
|
||||||
|
executable('schc', 'src/client.c', include_directories: include_dirs, install: true)
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define PORT 5555
|
||||||
|
#define BUFFER_SIZE 1024
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int sock;
|
||||||
|
struct sockaddr_in server_addr;
|
||||||
|
char buffer[BUFFER_SIZE];
|
||||||
|
|
||||||
|
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if (sock < 0) {
|
||||||
|
perror("socket");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
server_addr.sin_family = AF_INET;
|
||||||
|
server_addr.sin_port = htons(PORT);
|
||||||
|
inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr);
|
||||||
|
|
||||||
|
if (connect(sock, (struct sockaddr *) &server_addr, sizeof(server_addr)) <
|
||||||
|
0) {
|
||||||
|
perror("connect");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fork() == 0) {
|
||||||
|
// Процесс чтения
|
||||||
|
while (1) {
|
||||||
|
int valread = read(sock, buffer, BUFFER_SIZE);
|
||||||
|
if (valread > 0) {
|
||||||
|
buffer[valread] = '\0';
|
||||||
|
printf("%s", buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
char username[50];
|
||||||
|
fgets(username, 50, stdin);
|
||||||
|
username[strlen(username)-1] = '\0';
|
||||||
|
send(sock, username, 50, 0);
|
||||||
|
printf("username = %s\n", username);
|
||||||
|
// Процесс отправки
|
||||||
|
while (1) {
|
||||||
|
fgets(buffer, BUFFER_SIZE, stdin);
|
||||||
|
send(sock, buffer, strlen(buffer), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
#ifndef COLORS_H
|
||||||
|
#define COLORS_H
|
||||||
|
#define RESET "\033[0m"
|
||||||
|
#define GREEN "\033[0;32m" // GREEN
|
||||||
|
#define BLUE "\033[0;34m" // BLUE
|
||||||
|
#define YELLOW "\033[1;33m" // YELLOW
|
||||||
|
#define RED "\033[0;31m" // RED
|
||||||
|
#define BLACK "\033[0;30m" // BLACK
|
||||||
|
#define PURPLE "\033[0;35m" // PURPLE
|
||||||
|
#define CYAN "\033[0;36m" // CYAN
|
||||||
|
#define WHITE "\033[0;37m" // WHITE
|
||||||
|
#define BBLACK "\033[1;30m" // BLACK
|
||||||
|
#define BRED "\033[1;31m" // RED
|
||||||
|
#define BGREEN "\033[1;32m" // GREEN
|
||||||
|
#define BYELLOW "\033[1;33m" // YELLOW
|
||||||
|
#define BBLUE "\033[1;34m" // BLUE
|
||||||
|
#define BPURPLE "\033[1;35m" // PURPLE
|
||||||
|
#define BCYAN "\033[1;36m" // CYAN
|
||||||
|
#define BWHITE "\033[1;37m" // WHITE
|
||||||
|
#define UBLACK "\033[4;30m" // BLACK
|
||||||
|
#define URED "\033[4;31m" // RED
|
||||||
|
#define UGREEN "\033[4;32m" // GREEN
|
||||||
|
#define UYELLOW "\033[4;33m" // YELLOW
|
||||||
|
#define UBLUE "\033[4;34m" // BLUE
|
||||||
|
#define UPURPLE "\033[4;35m" // PURPLE
|
||||||
|
#define UCYAN "\033[4;36m" // CYAN
|
||||||
|
#define UWHITE "\033[4;37m" // WHITE
|
||||||
|
#define ON_BLACK "\033[40m" // BLACK
|
||||||
|
#define ON_RED "\033[41m" // RED
|
||||||
|
#define ON_GREEN "\033[42m" // GREEN
|
||||||
|
#define ON_YELLOW "\033[43m" // YELLOW
|
||||||
|
#define ON_BLUE "\033[44m" // BLUE
|
||||||
|
#define ON_PURPLE "\033[45m" // PURPLE
|
||||||
|
#define ON_CYAN "\033[46m" // CYAN
|
||||||
|
#define ON_WHITE "\033[47m" // WHITE
|
||||||
|
#define IBLACK "\033[0;90m" // BLACK
|
||||||
|
#define IRED "\033[0;91m" // RED
|
||||||
|
#define IGREEN "\033[0;92m" // GREEN
|
||||||
|
#define IYELLOW "\033[0;93m" // YELLOW
|
||||||
|
#define IBLUE "\033[0;94m" // BLUE
|
||||||
|
#define IPURPLE "\033[0;95m" // PURPLE
|
||||||
|
#define ICYAN "\033[0;96m" // CYAN
|
||||||
|
#define IWHITE "\033[0;97m" // WHITE
|
||||||
|
#define BIBLACK "\033[1;90m" // BLACK
|
||||||
|
#define BIRED "\033[1;91m" // RED
|
||||||
|
#define BIGREEN "\033[1;92m" // GREEN
|
||||||
|
#define BIYELLOW "\033[1;93m" // YELLOW
|
||||||
|
#define BIBLUE "\033[1;94m" // BLUE
|
||||||
|
#define BIPURPLE "\033[1;95m" // PURPLE
|
||||||
|
#define BICYAN "\033[1;96m" // CYAN
|
||||||
|
#define BIWHITE "\033[1;97m" // WHITE
|
||||||
|
#define ON_IBLACK "\033[0;100m" // BLACK
|
||||||
|
#define ON_IRED "\033[0;101m" // RED
|
||||||
|
#define ON_IGREEN "\033[0;102m" // GREEN
|
||||||
|
#define ON_IYELLOW "\033[0;103m" // YELLOW
|
||||||
|
#define ON_IBLUE "\033[0;104m" // BLUE
|
||||||
|
#define ON_IPURPLE "\033[0;105m" // PURPLE
|
||||||
|
#define ON_ICYAN "\033[0;106m" // CYAN
|
||||||
|
#define ON_IWHITE "\033[0;107m" // WHITE
|
||||||
|
|
||||||
|
#endif
|
||||||
+126
@@ -0,0 +1,126 @@
|
|||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <asm-generic/socket.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define PORT 5555
|
||||||
|
#define MAX_CLIENTS 10
|
||||||
|
#define BUFFER_SIZE 1024
|
||||||
|
|
||||||
|
struct client_t {
|
||||||
|
int sock;
|
||||||
|
char username[50];
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int server_fd;
|
||||||
|
struct client_t clients[MAX_CLIENTS];
|
||||||
|
struct sockaddr_in address;
|
||||||
|
int addrlen = sizeof(address);
|
||||||
|
fd_set readfds;
|
||||||
|
char buffer[BUFFER_SIZE];
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_CLIENTS; i++) {
|
||||||
|
clients[i].sock = 0;
|
||||||
|
bzero(clients[i].username, sizeof(clients[i].username));
|
||||||
|
}
|
||||||
|
|
||||||
|
server_fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if (server_fd < 0) {
|
||||||
|
perror("socket");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int opt = 1;
|
||||||
|
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
|
||||||
|
perror("setsockopt");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
address.sin_family = AF_INET;
|
||||||
|
address.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
address.sin_port = htons(PORT);
|
||||||
|
|
||||||
|
if (bind(server_fd, (struct sockaddr *) &address, sizeof(address)) < 0) {
|
||||||
|
perror("bind");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listen(server_fd, 5) < 0) {
|
||||||
|
perror("listen");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Chat server started on port %d\n", PORT);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
FD_ZERO(&readfds);
|
||||||
|
FD_SET(server_fd, &readfds);
|
||||||
|
int max_sd = server_fd;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_CLIENTS; i++) {
|
||||||
|
int sd = clients[i].sock;
|
||||||
|
if (sd > 0) FD_SET(sd, &readfds);
|
||||||
|
if (sd > max_sd) max_sd = sd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (select(max_sd + 1, &readfds, NULL, NULL, NULL) < 0) {
|
||||||
|
perror("select");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Новое подключение
|
||||||
|
if (FD_ISSET(server_fd, &readfds)) {
|
||||||
|
int new_socket = accept(server_fd, (struct sockaddr *) &address,
|
||||||
|
(socklen_t *) &addrlen);
|
||||||
|
|
||||||
|
printf("New connection: socket %d\n", new_socket);
|
||||||
|
read(new_socket, buffer, BUFFER_SIZE);
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_CLIENTS; i++) {
|
||||||
|
if (clients[i].sock == 0) {
|
||||||
|
clients[i].sock = new_socket;
|
||||||
|
strcpy(clients[i].username, buffer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Сообщения от клиентов
|
||||||
|
for (int i = 0; i < MAX_CLIENTS; i++) {
|
||||||
|
int sd = clients[i].sock;
|
||||||
|
char sd_username[50];
|
||||||
|
bzero(sd_username, sizeof(sd_username));
|
||||||
|
strcpy(sd_username, clients[i].username);
|
||||||
|
|
||||||
|
if (FD_ISSET(sd, &readfds)) {
|
||||||
|
int valread = read(sd, buffer, BUFFER_SIZE);
|
||||||
|
|
||||||
|
if (valread == 0) {
|
||||||
|
printf("Client disconnected: socket %d\n", sd);
|
||||||
|
close(sd);
|
||||||
|
clients[i].sock = 0;
|
||||||
|
bzero(clients[i].username, sizeof(clients[i].username));
|
||||||
|
} else {
|
||||||
|
buffer[valread] = '\0';
|
||||||
|
printf("from_socket: %d\n", sd);
|
||||||
|
printf("from_username: %s\n", sd_username);
|
||||||
|
printf("Message: %s\n", buffer);
|
||||||
|
|
||||||
|
// Рассылка всем другим
|
||||||
|
for (int j = 0; j < MAX_CLIENTS; j++) {
|
||||||
|
if (clients[j].sock != 0 && clients[j].sock != sd) {
|
||||||
|
send(clients[j].sock, buffer, strlen(buffer), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user