-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
364 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
#include <errno.h> | ||
#include <string.h> | ||
#include <unistd.h> | ||
#include <stdlib.h> | ||
#include <netdb.h> | ||
#include <sys/socket.h> | ||
#include <netinet/in.h> | ||
|
||
// Extracts newline from buf to msg and moves the buf | ||
int extract_message(char **buf, char **msg) | ||
{ | ||
char *newbuf; | ||
int i; | ||
|
||
*msg = 0; | ||
if (*buf == 0) | ||
return (0); | ||
i = 0; | ||
while ((*buf)[i]) | ||
{ | ||
if ((*buf)[i] == '\n') | ||
{ | ||
newbuf = calloc(1, sizeof(*newbuf) * (strlen(*buf + i + 1) + 1)); | ||
if (newbuf == 0) | ||
return (-1); | ||
strcpy(newbuf, *buf + i + 1); | ||
*msg = *buf; | ||
(*msg)[i + 1] = 0; | ||
*buf = newbuf; | ||
return (1); | ||
} | ||
i++; | ||
} | ||
return (0); | ||
} | ||
|
||
char *str_join(char *buf, char *add) | ||
{ | ||
char *newbuf; | ||
int len; | ||
|
||
if (buf == 0) | ||
len = 0; | ||
else | ||
len = strlen(buf); | ||
newbuf = malloc(sizeof(*newbuf) * (len + strlen(add) + 1)); | ||
if (newbuf == 0) | ||
return (0); | ||
newbuf[0] = 0; | ||
if (buf != 0) | ||
strcat(newbuf, buf); | ||
free(buf); | ||
strcat(newbuf, add); | ||
return (newbuf); | ||
} | ||
|
||
|
||
int main(int argc, char **argv) { | ||
|
||
int sockfd, connfd, len; | ||
struct sockaddr_in servaddr, cli; | ||
|
||
// socket create and verification | ||
sockfd = socket(AF_INET, SOCK_STREAM, 0); | ||
if (sockfd == -1) | ||
{ | ||
printf("socket creation failed...\n"); | ||
exit(0); | ||
} | ||
else | ||
printf("Socket successfully created..\n"); | ||
bzero(&servaddr, sizeof(servaddr)); | ||
|
||
// assign IP, PORT | ||
servaddr.sin_family = AF_INET; | ||
servaddr.sin_addr.s_addr = htonl(2130706433); //127.0.0.1 | ||
servaddr.sin_port = htons(8081); | ||
|
||
// Binding newly created socket to given IP and verification | ||
if ((bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr))) != 0) { | ||
printf("socket bind failed...\n"); | ||
exit(0); | ||
} | ||
else | ||
printf("Socket successfully binded..\n"); | ||
if (listen(sockfd, 10) != 0) { | ||
printf("cannot listen\n"); | ||
exit(0); | ||
} | ||
len = sizeof(cli); | ||
connfd = accept(sockfd, (struct sockaddr *)&cli, &len); | ||
if (connfd < 0) { | ||
printf("server acccept failed...\n"); | ||
exit(0); | ||
} | ||
else | ||
printf("server acccept the client...\n"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
#include <libc.h> | ||
|
||
char* ARG = "Wrong number of arguments\n"; | ||
char* FATAL = "Fatal error\n"; | ||
char ANONCMENT[200000], MSG[200000], BUFF[200000]; | ||
int sockfd, nclifd, nfds, id, ids[1024], ret; | ||
struct sockaddr_in servaddr, cli; | ||
fd_set fds, rfds; | ||
socklen_t clilen; | ||
|
||
void err(char *str) | ||
{ | ||
write(2, str, strlen(str)); | ||
exit(1); | ||
} | ||
|
||
void announcement(char *str, int cli) | ||
{ | ||
for(int fd = 0; fd < nfds; fd++) | ||
if (fd != cli && FD_ISSET(fd, &fds)) | ||
send(fd, str, strlen(str), 0); | ||
} | ||
|
||
void join_client(int fd) | ||
{ | ||
nfds = (fd >= nfds) ? fd+1 : nfds; | ||
ids[fd] = id++; | ||
bzero(ANONCMENT, sizeof(ANONCMENT)); | ||
sprintf(ANONCMENT, "server: client %d just arrived\n", ids[fd]); | ||
announcement(ANONCMENT, fd); | ||
FD_SET(fd, &fds); | ||
} | ||
|
||
void left_client(int fd) | ||
{ | ||
FD_CLR(fd, &fds); | ||
bzero(ANONCMENT, sizeof(ANONCMENT)); | ||
sprintf(ANONCMENT, "server: client %d just left\n", ids[fd]); | ||
announcement(ANONCMENT, fd); | ||
close(fd); | ||
} | ||
|
||
void share_msg(int fd) | ||
{ | ||
bzero(ANONCMENT, sizeof(ANONCMENT)); | ||
bzero(BUFF, sizeof(BUFF)); | ||
for(int i=0, j=0; MSG[i]; i++, j++) | ||
{ | ||
BUFF[j] = MSG[i]; | ||
if (MSG[i] == '\n') | ||
{ | ||
sprintf(ANONCMENT, "client %d: %s", ids[fd], BUFF); | ||
announcement(ANONCMENT, fd); | ||
j = -1; | ||
bzero(ANONCMENT, sizeof(ANONCMENT)); | ||
bzero(BUFF, sizeof(BUFF)); | ||
} | ||
} | ||
bzero(MSG, sizeof(MSG)); | ||
} | ||
|
||
void mini_serv() | ||
{ | ||
FD_ZERO(&fds); | ||
FD_SET(sockfd, &fds); | ||
nfds = sockfd+1; | ||
while(1) | ||
{ | ||
rfds = fds; | ||
if (select(nfds, &rfds, NULL, NULL, NULL) == -1) | ||
err(FATAL); | ||
for(int fd = 0; fd < nfds; fd++) | ||
{ | ||
if (!FD_ISSET(fd, &rfds)) | ||
continue; | ||
if (fd == sockfd) | ||
{ | ||
clilen = sizeof(cli); | ||
nclifd = accept(sockfd, (struct sockaddr *)&cli, &clilen); | ||
if (nclifd > 0) | ||
{ | ||
join_client(nclifd); | ||
break; | ||
} | ||
} | ||
else | ||
{ | ||
if (recv(fd, MSG, 199999, 0) <= 0) | ||
{ | ||
left_client(fd); | ||
break; | ||
} | ||
else | ||
share_msg(fd); | ||
} | ||
} | ||
} | ||
} | ||
|
||
int main(int argc, char **argv) | ||
{ | ||
if (argc != 2) | ||
err(ARG); | ||
sockfd = socket(AF_INET, SOCK_STREAM, 0); | ||
if (sockfd == -1) | ||
err(FATAL); | ||
bzero(&servaddr, sizeof(servaddr)); | ||
servaddr.sin_family = AF_INET; | ||
servaddr.sin_addr.s_addr = htonl(2130706433); | ||
servaddr.sin_port = htons(atoi(argv[1])); | ||
if (bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) | ||
err(FATAL); | ||
if (listen(sockfd, 10) == -1) | ||
err(FATAL); | ||
mini_serv(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import socket | ||
import sys | ||
|
||
host = 'localhost' | ||
port = 9999 | ||
address = (host, port) | ||
|
||
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | ||
server_socket.bind((address)) | ||
server_socket.listen(5) | ||
print ("Listening for client . . .") | ||
conn, address = server_socket.accept() | ||
print ("Connected to client at ", address) | ||
while True: | ||
try: | ||
output = conn.recv(2048) | ||
if output: | ||
print ("Message received from client:") | ||
print (output) | ||
|
||
except: | ||
sys.exit(0) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
Assignment name : mini_serv | ||
Expected files : mini_serv.c | ||
Allowed functions: write, close, select, socket, accept, listen, send, recv, bind, strstr, malloc, realloc, free, calloc, bzero, atoi, sprintf, strlen, exit, strcpy, strcat, memset | ||
-------------------------------------------------------------------------------- | ||
|
||
Write a program that will listen for client to connect on a certain port on 127.0.0.1 and will let clients to speak with each other | ||
|
||
This program will take as first argument the port to bind to | ||
If no argument is given, it should write in stderr "Wrong number of arguments" followed by a \n and exit with status 1 | ||
If a System Calls returns an error before the program start accepting connection, it should write in stderr "Fatal error" followed by a \n and exit with status 1 | ||
If you cant allocate memory it should write in stderr "Fatal error" followed by a \n and exit with status 1 | ||
|
||
Your program must be non-blocking but client can be lazy and if they don't read your message you must NOT disconnect them... | ||
|
||
Your program must not contains #define preproc | ||
Your program must only listen to 127.0.0.1 | ||
The fd that you will receive will already be set to make 'recv' or 'send' to block if select hasn't be called before calling them, but will not block otherwise. | ||
|
||
When a client connect to the server: | ||
- the client will be given an id. the first client will receive the id 0 and each new client will received the last client id + 1 | ||
- %d will be replace by this number | ||
- a message is sent to all the client that was connected to the server: "server: client %d just arrived\n" | ||
|
||
clients must be able to send messages to your program. | ||
- message will only be printable characters, no need to check | ||
- a single message can contains multiple \n | ||
- when the server receive a message, it must resend it to all the other client with "client %d: " before every line! | ||
|
||
When a client disconnect from the server: | ||
- a message is sent to all the client that was connected to the server: "server: client %d just left\n" | ||
|
||
Memory or fd leaks are forbidden | ||
|
||
To help you, you will find the file main.c with the beginning of a server and maybe some useful functions. (Beware this file use forbidden functions or write things that must not be there in your final program) | ||
|
||
Warning our tester is expecting that you send the messages as fast as you can. Don't do un-necessary buffer. | ||
|
||
Evaluation can be a bit longer than usual... | ||
|
||
Hint: you can use nc to test your program | ||
Hint: you should use nc to test your program | ||
Hint: To test you can use fcntl(fd, F_SETFL, O_NONBLOCK) but use select and NEVER check EAGAIN (man 2 send) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
Առաջադրանքի անունը՝ mini_serv | ||
Ակնկալվող ֆայլեր՝ mini_serv.c | ||
Թույլատրված ֆունկցիաներ՝ write, close, select, socket, accept, listen, send, recv, bind, strstr, malloc, realloc, free, calloc, bzero, atoi, sprintf, strlen, exit, strcpy, strcat, memset | ||
-------------------------------------------------------------------------------- | ||
|
||
Գրել ծրագիր, որը կսպասի մինչև հաճախորդը կմիանա 127.0.0.1 հասցեով միացման կետին(port) և թույլ կտա հաճախորդներին իրար հետ խոսել։ | ||
|
||
Այս ծրագիրը որպես առաջին արգումենտ վերցնում է միացման կետը։ | ||
Եթե ոչ մի արգումենտ տրված չէ, այն պետք է stderr-ում գրի «Wrong number of arguments»՝ հաջորդված \n-ով և դուրս է գա 1 վիճակով։ | ||
Եթե Համակարգային կանչերը սխալ է վերադարձնում մինչև ծրագիրը կսկսի կապեր ընդունել, այն պետք է stderr-ում գրի «Fatal error»՝ հաջորդված \n-ով և դուրս է գա 1 վիճակով։ | ||
Եթե հիշողությունը չեք կարողանում տեղակայել, այն պետք է գրի stderr-ում գրի «Fatal error»՝ հաջորդված \n և դուրս գա 1 վիճակով։ | ||
|
||
Ձեր ծրագիրը պետք է արգելափակող չլինի, բայց հաճախորդը կարող է ծույլ լինել ու եթե ձեր հաղորդագրությունը չկարդա, նրան պետք ՉԷ կապից անջատել։ | ||
|
||
|
||
Ձեր ծրագիրը չպիտի պարունակի #define preproc։ | ||
Ձեր ծրագիրը պետք է հետևի միայն 127.0.0.1-ին։ | ||
Ձեր ստացած fd-ին արդեն կարգավորված կլինի ստեղծել «recv» և «send»՝ արգելափակելու համար, եթե select-ը չի կանչվել նրանց կանչելուց առաջ, բայց այլ դեպքերում չի արգելափակի։ | ||
|
||
Երբ հաճախորդը միանում է սերվերին՝ | ||
- Հաճախորդին կտրվի id․ առաջին հաճախորդը կստանա id 0 և յուրաքանչյուր նոր հաճախորդ կստանա վերջին հաճախորդի id + 1 | ||
- %d-ն կփոխարինվի այս թվով | ||
- Սերվերին միացած բոլոր հաճախորդներին կուղարկվի հաղորդագրություն՝ «server: client %d just arrived\n» | ||
|
||
Հաճախորդները պետք է կարողանան հաղորդագրություններ ուղարկել ձեր ծրագրին։ | ||
- Հաղորդագրությունը միայն տպելի նիշերով է լինելու, ստուգելու կարիք չկա | ||
- Յուրաքանչյուր հաղորդագրությունը պետք է ավարտվի \n-ով։ | ||
- Երբ սերվերը հաղորդագրություն ստանա, այն պետք է դա ուղարկի մյուս բոլոր հաճախորդներին՝ հաղորդագրությունից առաջ «client %d:»-ով։ | ||
|
||
Երբ հաճախորդը սերվերից անջատվում է, | ||
- սերվերին կապված բոլոր հաճախորդներին նամակ է ուղարկվում՝ «server: client %d just left\n»։ | ||
|
||
Հիշողության կամ fd արտահոսքեր չեն թույլատրվում։ | ||
|
||
Ձեզ օգնելու համար, ֆայլի main.c-ն կգտնեք սերվերի սկզբնական տողերով ու որոշ օգտակար ֆունկցիաներով։ (Ուշադի՛ր եղեք այս ֆայլում չթույլատրված ֆունկցիաներ գործածելիս կամ այնպիսի բաներ գրելիս, որոնք ձեր վերջնական ծրագրում չպիտի լինեն) | ||
To help you, you will find the file main.c with the beginning of a server and maybe some useful functions. (Beware this file use forbidden functions or write things that must not be there in your final program) | ||
|
||
Զգուշացում։ Մեր փորձարկիչը ակնկալում է, որ հաղորդագրությունները ինչքան հնարավոր է արագ ուղարկեք։ Անիմաստ բուֆերներ պետք չէ անել։ | ||
|
||
Գնահատումը կարող է սովարականից մի քիչ երկար տևել | ||
|
||
Հուշում՝ կարող եք nc-ն գործածել ձեր ծրագիրը փորձարկելու համար։ | ||
Հուշում՝ պետք է nc-ն գործածեք ձեր ծրագիրը փորձարկելու համար։ | ||
Հուշում՝ փորձարկելու համար կարող եք գործածել fcntl(fd, F_SETFL, O_NONBLOCK), բայց գործածե՛ք select և ԱՅԼԵՎՍ ԵՐԲԵՔ մի՛ ստուգեք (man 2 send)։ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
Имя назначения : mini_serv | ||
Ожидаемые файлы : mini_serv.c | ||
Разрешенные функции : write, close, select, socket, accept, listen, send, recv, bind, strstr, malloc, realloc, free, calloc, bzero, atoi, sprintf, strlen, exit, strcpy, strcat, memset | ||
-------------------------------------------------------------------------------- | ||
|
||
Напишите программу, которая будет прослушивать подключение клиента к определенному порту на 127.0.0.1 и позволит клиентам разговаривать друг с другом | ||
|
||
Эта программа будет принимать в качестве первого аргумента порт для привязки | ||
Если аргумент не задан, он должен написать в stderr "Wrong number of arguments", за которым следует a \n и выйти со статусом 1 | ||
Если системный вызов возвращает ошибку до того, как программа начнет принимать соединение, она должна написать в stderr "Fatal error", а затем a \n и выйти со статусом 1 | ||
Если вы не можете выделить память, он должен написать в stderr "Fatal error", а затем a \n и выйти со статусом 1 | ||
|
||
Ваша программа должна быть неблокирующей, но клиент может быть ленивым, и если он не читает ваше сообщение, вы не должны отключать его... | ||
|
||
Ваша программа не должна содержать #define preproc | ||
Ваша программа должна слушать только 127.0.0.1 | ||
Fd, который вы получите, уже будет настроен на блокировку 'recv' или 'send', если select не был вызван до их вызова, но в противном случае не будет заблокирован. | ||
|
||
Когда клиент подключается к серверу: | ||
- клиенту будет выдано удостоверение личности. первый клиент получит идентификатор 0, а каждый новый клиент получит последний идентификатор клиента + 1 | ||
- %d будет заменено на это число | ||
- всем клиентам, которые были подключены к серверу, отправляется сообщение: "server: client %d just arrived\n" | ||
|
||
клиенты должны иметь возможность отправлять сообщения в вашу программу. | ||
- сообщение будет состоять только из печатаемых символов, проверять его не нужно | ||
- одно сообщение может содержать несколько \n | ||
- когда сервер получает сообщение, он должен повторно отправить его всем другим клиентам с "client %d:" перед каждой строкой! | ||
|
||
Когда клиент отключается от сервера: | ||
- всем клиентам, которые были подключены к серверу, отправляется сообщение: "server: client %d just left\n" | ||
|
||
Утечки памяти или fd запрещены | ||
|
||
Чтобы помочь вам, вы найдете файл main.c с началом работы сервера и, возможно, некоторые полезные функции. (Остерегайтесь, чтобы этот файл использовал запрещенные функции или писал вещи, которых не должно быть в вашей окончательной программе) | ||
|
||
Предупреждение наш тестер ожидает, что вы будете отправлять сообщения так быстро, как только сможете. Не делайте ненужного буфера. | ||
|
||
Оценка может быть немного дольше, чем обычно... | ||
|
||
Подсказка: вы можете использовать nc для тестирования вашей программы | ||
Подсказка: вы должны использовать nc для тестирования вашей программы | ||
Подсказка: Для тестирования вы можете использовать fcntl(fd, F_SETFL, O_NONBLOCK), но используйте select и НИКОГДА НЕ проверяйте EAGAIN (man 2 send) |