diff --git a/.gitignore b/.gitignore index f2e1fa5..45f40f1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ - # Created by https://www.gitignore.io/api/c++,latex,cmake,netbeans,qtcreator,visualstudio +### Intellij IDEA ### +/.idea/* + ### C++ ### # Prerequisites *.d diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..ab79c8e --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.5) +project(NetworksLab2019HSE) + +set(CMAKE_CXX_STANDARD 14) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -Iinclude -pedantic -Wextra -pthread") + +include_directories(./include) + +add_executable(NetworksLab2019HSE + src/Client.cpp + src/CurrencyClientApplication.cpp + src/Currency.cpp + ) \ No newline at end of file diff --git a/CurrencyApplicationProtocol b/CurrencyApplicationProtocol new file mode 100644 index 0000000..18a8199 --- /dev/null +++ b/CurrencyApplicationProtocol @@ -0,0 +1,68 @@ +Протокол разрабатывается исходя из подхода "запрос-ответ", так как он очень хорошо подходит для задачи: +клиенты запрашивают какое-то действие с валютой, сервер ее выполняет. + +Данные на сервере: + Массив валют, где валюта это: + Название валюты - 16 байта + История курса валюты - N * 4 байта (каждое значение курса это 4 байта) + +... - повторение описанных блоков выше. + +Клиент и сервер обмениваются пакетами размера 508 байт (либо меньше, если размер сообщения небольшой). +В начале каждого пакета с запросом клиент передает -- номер его сессии, +и при получении ответа от сервера обрабатывает только те пакеты, которые соответствуют этой сессии. +Сделано это для того, чтобы если пакет от сервера задержался и запрос от клиента был отправлен повторно, +ошибочно не учитывать уже невалидный пакет. Таким образом, пакеты с неправильным id игнорируются. +Перед отправкой ответа с сервера содержимое сообщения разбивается на пакеты по 508 байт. +В начало каждого записывается служебная информация: + -- номер сессии, количество пакетов и порядковый номер текущего соответственно. +Клиент расставляет пришедшие пакеты в правильном порядке, при нехватке пакетов отправляет запрос заново с новым номером сессии. + +Поддерживаемые типы запросов: + 0. Получение и вывод списка валют с котировками/изменениями + Номер команды: 0. + + Клиент отправляет: "<номер команды: 4 байта>", + + Сервер отвечает: + "<название валюты: 16 байт><текущий курс: 4 байта><есть ли предыдущий курс: 1 байт><абсолютное приращение: 4 байта><относительное приращение: 4 байта>"..., + если предыдущего курса нет, то абсолютное и относительное значения равны нулям и игнорируются, + относительное значение выражается в процентах и округляется до целых. + Формулы: + абсолютное = current - previous + относительное = (current * 100.0) / previous + + 1. Передача команды на добавление валюты + Номер команды: 1. + + Клиент отправляет: "<номер команды: 4 байта><название валюты: 16 байт><текущий курс: 4 байта>", + + Сервер отвечает: + "<успех запроса: 1 байт>", + возвращает 1 если такой валюты еще не было, 0 если такая валюта была. + + 2. Передача команды на удаление валюты + Номер команды: 2. + + Клиент отправляет: "<номер команды: 4 байта><название валюты: 16 байт>", + + Сервер отвечает: + "<успех запроса: 1 байт>", + возвращает 1 если такая валюта была и была удалена успешно, 0 если такой валюты не было. + + 3. Передача команды на добавление курса валюты + Номер команды: 3. + + Клиент отправляет: "<номер команды: 4 байта><название валюты: 16 байт><новый курс: 4 байта>", + + Сервер отвечает: + "<успех запроса: 1 байт>", + возвращает 1 если успешно выставлен новый курс, 0 иначе. + + 4. Получение истории котировок валюты + Номер команды: 4. + + Клиент отправляет: "<номер команды: 4 байта><название валюты: 16 байт>", + + Сервер отвечает: +"<курс1: 4 байта><курс2: 4 байта>"... \ No newline at end of file diff --git a/include/Client.h b/include/Client.h new file mode 100644 index 0000000..2e874e3 --- /dev/null +++ b/include/Client.h @@ -0,0 +1,69 @@ +// +// Created by mikhail on 03.02.19. +// + +#ifndef NETWORKSLAB2019HSE_CLIENT_H +#define NETWORKSLAB2019HSE_CLIENT_H + + +#include +#include +#include "Currency.h" + +class Client { +public: + Client(const std::string &server_ip, uint16_t portno); + + const std::vector list(); + + bool addCurrency(const Currency ¤cy); + + bool addRate(const Currency ¤cy, int32_t new_rate); + + bool remove(const Currency ¤cy); + + Currency getCurrencyWithHistory(const Currency ¤cy); + + virtual ~Client(); + +private: + struct sockaddr_in *si_other; + const int sockfd; + int32_t request_id = 0; + int si_other_len; + static const size_t BUFFER_INITIAL_LENGTH = 1024; + static const size_t CURRENCY_NAME_SIZE_IN_LIST = 16; + static const size_t MAX_SIZE_OF_PACKET = 508; + static const size_t TIMOUT_SECONDS = 30; + + const std::vector get_message_with_request_id(const std::vector &message); + + const std::vector send_and_receive(const std::vector &message); + + void write_request_id(std::vector &buffer); + + bool is_all_packets_received(const std::map> &packets, int number_of_packets) const; + + std::vector construct_message_from_packets(const std::map> &packets) const; + + void write_command(std::vector &buffer, int32_t command_no) const; + + const std::vector translate_list_message(std::vector &message) const; + + void write_string(std::vector &buffer, const std::string ¤cy_name) const; + + void write_int32(std::vector &buffer, int32_t rate) const; + + std::vector read_response() const; + + bool translate_add_message(std::vector &message) const; + + bool translate_remove_message(std::vector &message) const; + + std::vector translate_get_currency_history_message(std::vector &message) const; + + void send_request(const std::vector &buffer) const; +}; + + +#endif //NETWORKSLAB2019HSE_CLIENT_H diff --git a/include/Currency.h b/include/Currency.h new file mode 100644 index 0000000..95ff5f8 --- /dev/null +++ b/include/Currency.h @@ -0,0 +1,46 @@ +// +// Created by mikhail on 03.02.19. +// + +#ifndef NETWORKSLAB2019HSE_CURRENCY_H +#define NETWORKSLAB2019HSE_CURRENCY_H + + +#include +#include + +class Currency { +public: + Currency(std::string name); + + Currency(std::string name, std::vector rates); + + Currency(std::string name, int32_t current_rate); + + Currency(std::string name, int32_t current_rate, int32_t absolute_change, int32_t relative_change); + + const std::string &get_name() const; + + int32_t get_current_rate() const; + + int32_t get_rate(size_t i) const; + + const std::vector& get_rates() const; + + int32_t get_absolute_change() const; + + int32_t get_relative_change() const; + + bool operator==(const Currency &rhs) const; + + bool operator!=(const Currency &rhs) const; + +private: + std::string name; + std::vector rates; + int32_t absolute_change; + int32_t relative_change; +}; + + +#endif //NETWORKSLAB2019HSE_CURRENCY_H diff --git a/include/CurrencyClientApplication.h b/include/CurrencyClientApplication.h new file mode 100644 index 0000000..69f7ab4 --- /dev/null +++ b/include/CurrencyClientApplication.h @@ -0,0 +1,26 @@ +// +// Created by mikhail on 03.02.19. +// + +#ifndef NETWORKSLAB2019HSE_CURRENCYCLIENTAPPLICATION_H +#define NETWORKSLAB2019HSE_CURRENCYCLIENTAPPLICATION_H + + +#include "Client.h" + +class CurrencyClientApplication { +public: + void run(); + + CurrencyClientApplication(const std::string &host, uint16_t portno); + +private: + std::string host; + uint16_t portno; + Client client = Client(host, portno); + + void printUsage(); +}; + + +#endif //NETWORKSLAB2019HSE_CURRENCYCLIENTAPPLICATION_H diff --git a/src/Client.cpp b/src/Client.cpp new file mode 100644 index 0000000..02021a5 --- /dev/null +++ b/src/Client.cpp @@ -0,0 +1,272 @@ +// +// Created by mikhail on 03.02.19. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const std::vector Client::get_message_with_request_id(const std::vector &message) { + std::vector send_buffer; + write_request_id(send_buffer); + send_buffer.insert(send_buffer.end(), message.begin(), message.end()); + return send_buffer; +} + +const std::vector Client::send_and_receive(const std::vector &message) { + bool got_all_message = false; + std::vector response; + while(!got_all_message) { + send_request(get_message_with_request_id(message)); + + try { + response = read_response(); + } catch (const char *timeout_exception) { + continue; + } + got_all_message = true; + } + return response; +} + +const std::vector Client::list() { + int32_t command_no = 0; + auto write_buffer = std::vector(); + + write_command(write_buffer, command_no); + + auto response = send_and_receive(write_buffer); + return translate_list_message(response); +} + + +bool Client::addCurrency(const Currency ¤cy) { + int32_t command_no = 1; + auto write_buffer = std::vector(); + + write_command(write_buffer, command_no); + write_string(write_buffer, currency.get_name()); + write_int32(write_buffer, currency.get_current_rate()); + + auto response = send_and_receive(write_buffer); + return translate_add_message(response); +} + +bool Client::remove(const Currency ¤cy) { + int32_t command_no = 2; + auto write_buffer = std::vector(); + + write_command(write_buffer, command_no); + write_string(write_buffer, currency.get_name()); + + auto response = send_and_receive(write_buffer); + return translate_remove_message(response); +} + +bool Client::addRate(const Currency ¤cy, int32_t new_rate) { + int32_t command_no = 3; + auto write_buffer = std::vector(); + + write_command(write_buffer, command_no); + write_string(write_buffer, currency.get_name()); + write_int32(write_buffer, new_rate); + + auto response = send_and_receive(write_buffer); + return translate_add_message(response); +} + +Currency Client::getCurrencyWithHistory(const Currency ¤cy) { + auto write_buffer = std::vector(); + int32_t command_no = 4; + + write_command(write_buffer, command_no); + write_string(write_buffer, currency.get_name()); + + auto response = send_and_receive(write_buffer); + return Currency(currency.get_name(), translate_get_currency_history_message(response)); +} + +Client::Client(const std::string &server_ip, uint16_t portno) : sockfd(socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) { + if (sockfd < 0) { + perror("ERROR opening socket"); + exit(1); + } + + struct timeval tv{}; + tv.tv_sec = TIMOUT_SECONDS; + tv.tv_usec = 0; + if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { + perror("Error: cannot set timeout for socket"); + exit(1); + } + + si_other = new sockaddr_in(); + bzero((char *) si_other, sizeof(si_other)); + si_other->sin_family = AF_INET; + si_other->sin_port = htons(portno); + if (inet_aton(server_ip.c_str(), &(si_other->sin_addr)) == 0) { + perror("inet_aton() failed\n"); + exit(1); + } + si_other_len = sizeof(*si_other); +} + +Client::~Client() { + close(sockfd); + delete(si_other); +} + +template +void insert_bytes(std::vector &container, const T &value) { + const auto *bytes = reinterpret_cast(&value); + container.insert(container.end(), bytes, bytes + sizeof(T)); +} + +int32_t read_int32(std::vector::iterator &it) { + int8_t bytes[] = {it[0], it[1], it[2], it[3]}; + int32_t val = *((int*)bytes); + it += sizeof(int32_t); + return val; +} + +bool read_bool(std::vector::iterator &it) { + bool val = it[0]; + it += sizeof(bool); + return val; +} + +std::string read_string(std::vector::iterator &it, size_t len) { + std::string str(it, it + len); + str.erase(std::find(str.begin(), str.end(), '\0'), str.end()); + it += len; + return str; +} + +void Client::write_request_id(std::vector &buffer) { + request_id++; + insert_bytes(buffer, request_id); +} + +void Client::write_command(std::vector &buffer, int32_t command_no) const { + insert_bytes(buffer, command_no); +} + +bool Client::translate_remove_message(std::vector &message) const { + auto it = message.begin(); + return read_bool(it); +} + +std::vector Client::translate_get_currency_history_message(std::vector &message) const { + std::vector history; + for (auto it = message.begin(); it < message.end();) { + history.push_back(read_int32(it)); + } + return history; +} + +bool Client::translate_add_message(std::vector &message) const { + auto it = message.begin(); + return read_bool(it); +} + +const std::vector Client::translate_list_message(std::vector &message) const { + std::vector currencies; + for (auto it = message.begin(); it < message.end();) { + std::string currency_name = read_string(it, CURRENCY_NAME_SIZE_IN_LIST); + int32_t current_rate = read_int32(it); + bool has_change = read_bool(it); + int32_t absolute_change = read_int32(it); + int32_t relative_change = read_int32(it); + if (has_change) { + currencies.emplace_back(currency_name, current_rate, absolute_change, relative_change); + } else { + currencies.emplace_back(currency_name, current_rate); + } + } + return currencies; +} + +void Client::write_string(std::vector &buffer, const std::string ¤cy_name) const { + std::string string_to_write(currency_name); + string_to_write.resize(CURRENCY_NAME_SIZE_IN_LIST, 0); + buffer.insert(buffer.end(), string_to_write.begin(), string_to_write.end()); +} + +void Client::write_int32(std::vector &buffer, int32_t rate) const { + insert_bytes(buffer, rate); +} + +std::vector Client::read_response() const { + bool all_packets_received = false; + auto packets = std::map>(); + + while (!all_packets_received) { + auto read_buffer = std::vector(BUFFER_INITIAL_LENGTH); + ssize_t bytes_number = recvfrom(sockfd, read_buffer.data(), read_buffer.size(), 0, + (struct sockaddr *) si_other, (socklen_t *) &si_other_len); + + if (errno == EAGAIN || errno == EWOULDBLOCK) { + perror("Timout reached for recvfrom, probably packages was lost or request wasn't received, sending again." + " Error:"); + throw "TIMEOUT"; + } + if (bytes_number == 0) { + perror("Connection was closed by server, please try later"); + exit(1); + } + if (bytes_number < 0) { + perror("ERROR reading from socket"); + exit(1); + } + read_buffer.resize(static_cast(bytes_number)); + auto it = read_buffer.begin(); + int32_t read_request_id = read_int32(it); + if (read_request_id != request_id) { + continue; + } + int32_t read_number_of_packets = read_int32(it); + int32_t packet_id = read_int32(it); + auto packet_message = std::vector(it, read_buffer.end()); + packets[packet_id] = packet_message; + all_packets_received = is_all_packets_received(packets, read_number_of_packets); + } + return construct_message_from_packets(packets); +} + +std::vector Client::construct_message_from_packets(const std::map> &packets) const { + std::vector message; + for (const auto& packet : packets) { + message.insert(message.end(), packet.second.begin(), packet.second.end()); + } + return message; +} + +bool Client::is_all_packets_received +(const std::map> &packets, int number_of_packets) const { + for (int packet_id = 0; packet_id < number_of_packets; packet_id++) { + if (packets.count(packet_id) == 0) { + return false; + } + } + return true; +} + +void Client::send_request(const std::vector &buffer) const { + if (buffer.size() > MAX_SIZE_OF_PACKET) { + perror("ERROR sending data, packet size is more then maximum size"); + exit(1); + } + auto return_code = sendto(sockfd, buffer.data(), buffer.size(), 0, + (struct sockaddr *) si_other, static_cast(si_other_len)); + if (return_code < 0) { + perror("ERROR sending data to socket"); + exit(1); + } +} diff --git a/src/Currency.cpp b/src/Currency.cpp new file mode 100644 index 0000000..83279ab --- /dev/null +++ b/src/Currency.cpp @@ -0,0 +1,71 @@ +#include + +// +// Created by mikhail on 03.02.19. +// + +#include + +Currency::Currency(std::string name, std::vector rates) : name(std::move(name)), rates(std::move(rates)) { + if (rates.size() >= 2) { + int32_t current = get_current_rate(), previous = get_rate(rates.size() - 2); + absolute_change = current - previous; + relative_change = static_cast((current * 100.0) / previous ); + } else { + absolute_change = -1; + relative_change = -1; + } +} + +Currency::Currency(std::string name) : name(std::move(name)) { + rates = {}; + absolute_change = -1; + relative_change = -1; +} + +Currency::Currency(std::string name, int32_t current_rate) : name(std::move(name)) { + rates = {current_rate}; + absolute_change = -1; + relative_change = -1; +} + +Currency::Currency(std::string name, int32_t current_rate, int32_t absolute_change, int32_t relative_change) : + name(std::move(name)), absolute_change(absolute_change), relative_change(relative_change) { + rates = {current_rate - absolute_change, current_rate}; +} + +const std::string &Currency::get_name() const { + return name; +} + +int32_t Currency::get_current_rate() const { + return get_rate(rates.size() - 1); +} + +int32_t Currency::get_rate(size_t i) const { + return i < rates.size() ? rates[i] : -1; +} + +const std::vector& Currency::get_rates() const { + return rates; +} + +int32_t Currency::get_absolute_change() const { + return absolute_change; +} + +int32_t Currency::get_relative_change() const { + return relative_change; +} + +bool Currency::operator==(const Currency &rhs) const { + return name == rhs.name && + rates == rhs.rates && + absolute_change == rhs.absolute_change && + relative_change == rhs.relative_change; +} + +bool Currency::operator!=(const Currency &rhs) const { + return !(rhs == *this); +} + diff --git a/src/CurrencyClientApplication.cpp b/src/CurrencyClientApplication.cpp new file mode 100644 index 0000000..7b5b44d --- /dev/null +++ b/src/CurrencyClientApplication.cpp @@ -0,0 +1,89 @@ +// +// Created by mikhail on 03.02.19. +// + +#include +#include + +int main(int argc, char *argv[]) { + if (argc < 3) { + fprintf(stderr, "usage: .%s \n", argv[0]); + return 0; + } + std::string hostname = argv[1]; + auto portno = static_cast(strtol(argv[2], nullptr, 10)); + CurrencyClientApplication(hostname, portno).run(); + return 0; +} + +void CurrencyClientApplication::run() { + printUsage(); + + bool toExit = false; + while (!toExit) { + std::string command; + std::cout << ">"; + std::cin >> command; + if (command == "list") { + auto currencies = client.list(); + std::cout << "RESPONSE:\n"; + for (const auto ¤cy : currencies) { + std::cout << currency.get_name() << " " << currency.get_absolute_change() << + " " << currency.get_relative_change() << "\n"; + } + } else if (command == "addCurrency") { + std::string currency_name; + int32_t currency_rate; + std::cin >> currency_name >> currency_rate; + if (client.addCurrency(Currency(currency_name, currency_rate))) { + std::cout << "Done\n"; + } else { + std::cout << "Currency already exists\n"; + } + } else if (command == "removeCurrency") { + std::string currency_name; + std::cin >> currency_name; + if (client.remove(Currency(currency_name))) { + std::cout << "Done\n"; + } else { + std::cout << "Currency doesn't exist\n"; + } + } else if (command == "addRate") { + std::string currency_name; + int32_t new_rate; + std::cin >> currency_name >> new_rate; + if (client.addRate(Currency(currency_name), new_rate)) { + std::cout << "Done\n"; + } else { + std::cout << "Currency doesn't exist\n"; + } + } else if (command == "getCurrencyHistory") { + std::string currency_name; + std::cin >> currency_name; + Currency currency_with_history = client.getCurrencyWithHistory(Currency(currency_name)); + std::cout << "RATES: "; + for (auto rate : currency_with_history.get_rates()) { + std::cout << rate << " "; + } + std::cout << "\n"; + } else if (command == "exit") { + toExit = true; + } else { + std::cout << "UNKNOWN COMMAND\n"; + } + } +} + +void CurrencyClientApplication::printUsage() { + std::cout << "Commands:\n" + << "list - list currencies with rate and rate differences\n" + << "addCurrency - adds new currency\n" + << "removeCurrency \n" + << "addRate - adds new rate for given currency\n" + << "getCurrencyHistory - returns rate history of given currency\n" + << "exit - to exit client application\n" + << "\n"; +} + +CurrencyClientApplication::CurrencyClientApplication(const std::string &host, uint16_t portno) : host(host), + portno(portno) {} \ No newline at end of file diff --git a/tcp/client/.gitkeep b/tcp/client/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/tcp/server/.gitkeep b/tcp/server/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/tcp_template/client_linux/CMakeLists.txt b/tcp_template/client_linux/CMakeLists.txt deleted file mode 100644 index 311326d..0000000 --- a/tcp_template/client_linux/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -cmake_minimum_required(VERSION 2.8) -project(client_linux) - -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra") - -set(SOURCE_FILES main.c) -add_executable(client_linux ${SOURCE_FILES}) \ No newline at end of file diff --git a/tcp_template/client_linux/main.c b/tcp_template/client_linux/main.c deleted file mode 100644 index ad0c290..0000000 --- a/tcp_template/client_linux/main.c +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include - -#include -#include -#include - -#include - -int main(int argc, char *argv[]) { - int sockfd, n; - uint16_t portno; - struct sockaddr_in serv_addr; - struct hostent *server; - - char buffer[256]; - - if (argc < 3) { - fprintf(stderr, "usage %s hostname port\n", argv[0]); - exit(0); - } - - portno = (uint16_t) atoi(argv[2]); - - /* Create a socket point */ - sockfd = socket(AF_INET, SOCK_STREAM, 0); - - if (sockfd < 0) { - perror("ERROR opening socket"); - exit(1); - } - - server = gethostbyname(argv[1]); - - if (server == NULL) { - fprintf(stderr, "ERROR, no such host\n"); - exit(0); - } - - bzero((char *) &serv_addr, sizeof(serv_addr)); - serv_addr.sin_family = AF_INET; - bcopy(server->h_addr, (char *) &serv_addr.sin_addr.s_addr, (size_t) server->h_length); - serv_addr.sin_port = htons(portno); - - /* Now connect to the server */ - if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { - perror("ERROR connecting"); - exit(1); - } - - /* Now ask for a message from the user, this message - * will be read by server - */ - - printf("Please enter the message: "); - bzero(buffer, 256); - fgets(buffer, 255, stdin); - - /* Send message to the server */ - n = write(sockfd, buffer, strlen(buffer)); - - if (n < 0) { - perror("ERROR writing to socket"); - exit(1); - } - - /* Now read server response */ - bzero(buffer, 256); - n = read(sockfd, buffer, 255); - - if (n < 0) { - perror("ERROR reading from socket"); - exit(1); - } - - printf("%s\n", buffer); - return 0; -} \ No newline at end of file diff --git a/tcp_template/server_linux/CMakeLists.txt b/tcp_template/server_linux/CMakeLists.txt deleted file mode 100644 index ac88ba4..0000000 --- a/tcp_template/server_linux/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -cmake_minimum_required(VERSION 2.8) -project(server_linux) - -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra") - -set(SOURCE_FILES main.c) -add_executable(server_linux ${SOURCE_FILES}) \ No newline at end of file diff --git a/tcp_template/server_linux/main.c b/tcp_template/server_linux/main.c deleted file mode 100644 index 30c7084..0000000 --- a/tcp_template/server_linux/main.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include - -#include -#include -#include - -#include - -int main(int argc, char *argv[]) { - int sockfd, newsockfd; - uint16_t portno; - unsigned int clilen; - char buffer[256]; - struct sockaddr_in serv_addr, cli_addr; - ssize_t n; - - /* First call to socket() function */ - sockfd = socket(AF_INET, SOCK_STREAM, 0); - - if (sockfd < 0) { - perror("ERROR opening socket"); - exit(1); - } - - /* Initialize socket structure */ - bzero((char *) &serv_addr, sizeof(serv_addr)); - portno = 5001; - - serv_addr.sin_family = AF_INET; - serv_addr.sin_addr.s_addr = INADDR_ANY; - serv_addr.sin_port = htons(portno); - - /* Now bind the host address using bind() call.*/ - if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { - perror("ERROR on binding"); - exit(1); - } - - /* Now start listening for the clients, here process will - * go in sleep mode and will wait for the incoming connection - */ - - listen(sockfd, 5); - clilen = sizeof(cli_addr); - - /* Accept actual connection from the client */ - newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); - - if (newsockfd < 0) { - perror("ERROR on accept"); - exit(1); - } - - /* If connection is established then start communicating */ - bzero(buffer, 256); - n = read(newsockfd, buffer, 255); // recv on Windows - - if (n < 0) { - perror("ERROR reading from socket"); - exit(1); - } - - printf("Here is the message: %s\n", buffer); - - /* Write a response to the client */ - n = write(newsockfd, "I got your message", 18); // send on Windows - - if (n < 0) { - perror("ERROR writing to socket"); - exit(1); - } - - return 0; -} diff --git a/udp/client/.gitkeep b/udp/client/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/udp/server/.gitkeep b/udp/server/.gitkeep deleted file mode 100644 index e69de29..0000000