MIPI_AdvancedC_FRTK/Seminar1/HW/client_bytestuff.c
2024-11-14 08:45:50 +03:00

208 lines
7.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*!
* Simple chat program (client side).cpp - http://github.com/hassanyf
* Version - 2.0.1
*
* Copyright (c) 2016 Hassan M. Yousuf
*/
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
int main()
{
/* ---------- ИНИЦИАЛИЗАЦИЯ ПЕРЕМЕННЫХ КЛИЕНТА---------- */
/*
1. client - файл-дескриптор, хранящий значение сокета,
которые вернула система при подключении к серверу.
2. portNum нужен для хранения номера порта, на котором происходит соединение.
3. isExit - булевая переменная, признак завершения программы.
4. Клиент считывает сообщение из сокета соединения в буффер обмена для приема/отправки данных к/от сервера
5. sockaddr_in - структура, содержащая интернет адрес, с которым будет установлено соединение.
Эта структура уже определена в netinet/in.h, поэтому нет необходимости
заново ее задавать.
DEFINITION:
struct sockaddr_in
{
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
6. serv_addr будет содержать адрес сервера
*/
int client;
int portNum = 1500; // Номер порта один для сервера и клиента!
bool isExit = false;
int bufsize = 1024;
char buffer[bufsize];
char* ip = "127.0.0.1";
struct sockaddr_in server_addr;
/*
Socket() функция создает новый сокет.
На вход получает 3 аргумента,
a. AF_INET: доменный адрес сокета.
b. SOCK_STREAM: тип сокета. Потоковый сокет, в котором сообщение
читается последовательным потоком(TCP).
c. Третий это аргумент протокола: всегда должен быть 0.
Операционная система выберет самый подходящий протокол.
Функция возвращает файл-дескриптор целое число - соединение, которое используется для всех ссылок
на этот сокет. Если произошла ошибка соединения, то возвращается -1.
*/
/* ---------- УСТАНОВКА СОКЕТ ПОДКЛЮЧЕНИЯ ----------*/
/* --------------- socket() функция ------------------*/
client = socket(AF_INET, SOCK_STREAM, 0);
printf("CLIENT\n");
if (client < 0)
{
printf("Error establishing socket...\n");
exit(1);
}
printf("=> Socket client has been created...\n");
/*
Переменная serv_addr - это структура sockaddr_in.
sin_family содержит код для адресной семьи.
Всегда должна быть установлена AF_INET.
htons() переводит номер порта из порядка байтов хоста
в номер порта в порядке байтов сети.
*/
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(portNum);
// эта функция возвращает 1, если IP-адрес действительный
// и 0, если недействительный
// inet_pton переводит IP-адрес в пакеты
// inet_ntoa переводит обратно из пакета в IP-адрес
inet_pton(AF_INET, ip, &server_addr.sin_addr);
/* ---------- СОЕДИНЕНИЕ СОКЕТА ---------- */
/* ---------------- connect() ---------------- */
if (connect(client,(struct sockaddr *)&server_addr, sizeof(server_addr)) == 0)
printf("=> Connection to the server %s with port number: %d\n",inet_ntoa(server_addr.sin_addr),portNum);
if (connect(client,(struct sockaddr *)&server_addr, sizeof(server_addr)) == 0)
printf("=> Connection to the server port number: %d \n",portNum);
/*
Функция connect вызывается клиентом для установки соединения с сервером.
Ей нужны 3 аргумента: файловый дескриптор сокета, адрес хоста, к которому
клиент хочет подключится (включая номер порта), и размер адреса.
Функция возвращает 0 при успехе и 1 при неудаче.
Примечание: клиенту нужно знать номер порта сервера,
а не свой номер порта.
*/
printf("=> Awaiting confirmation from the server...\n");
recv(client, buffer, bufsize, 0);
printf("=> Connection confirmed, you are good to go...\n");
printf("\n\n=> Enter # to end the connection\n");
// При достижении соединения, клиент может послать сообщение первым.
do {
char c;
printf("Client: ");
c = 0x7E;
send(client, &c, 1, 0); //SOP
do
{
c = getchar();
if(c == 0x7E)
{
c = 0x7D; send(client, &c, 1, 0);
c = 0x5E; send(client, &c, 1, 0);
continue;
}
if(c == 0x7D)
{
c = 0x7D; send(client, &c, 1, 0);
c = 0x5D; send(client, &c, 1, 0);
continue;
}
send(client, &c, 1, 0);
if(c == '#')
{
isExit = true;
break;
}
} while (c != '\n');
c = 0x7E;
send(client, &c, 1, 0); //EOP
printf("Server: ");
do
{
recv(client, &c, 1, 0);
} while (c != 0x7E); //SOP
recv(client, &c, 1, 0);
while (c != 0x7E) //EOP
{
if(c == 0x7D)
{
recv(client, &c, 1, 0);
if(c == 0x5E)
{
c = 0x7E;
}
else if(c == 0x5D)
{
c = 0x7D;
}
else
{
printf("%c", 0x7D);
continue;
}
}
printf("%c", c);
if (c == '#')
{
isExit = true;
}
recv(client, &c, 1, 0);
}
} while (!isExit);
/* ---------------- ЗАВЕРШЕНИЕ СОЕДИНЕНИЯ ------------- */
/* ----------------- close() --------------- */
/*
Как только сервер нажмет # для завершения соединения,
цикл завершится и закроет серверное сокет соединение
и клиентсткое соединение.
*/
printf("\n=> Connection terminated.\n\nGoodbye...\n");
close(client);
return 0;
}