From 89bf2d21dd7b1e42e14c70f8fce9e32aba59f15e Mon Sep 17 00:00:00 2001 From: Windrag Date: Mon, 11 Jan 2021 22:03:19 +0300 Subject: [PATCH] initial commit --- CMakeLists.txt | 7 +++ src/client.cpp | 126 ++++++++++++++++++++++++++++++++++++++++++++++ src/server.cpp | 133 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 266 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 src/client.cpp create mode 100644 src/server.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..e5207452 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.0) +project(messenger) +add_executable(client src/client.cpp) +add_executable(server src/server.cpp) +find_library(PH pthread) +target_link_libraries(server ${PH}) +target_link_libraries(client ${PH}) \ No newline at end of file diff --git a/src/client.cpp b/src/client.cpp new file mode 100644 index 00000000..e48cfac4 --- /dev/null +++ b/src/client.cpp @@ -0,0 +1,126 @@ +#include +#include +#include +#include +#include +#include +#include +#include + + +#define DEF_PORT 8888 +#define DEF_IP "127.0.0.1" +int readFix(int sock, char** buf, char** name, long* time, int flags); +int sendFix(int sock, char* buf, char* name, int flags); +void* reader(void* arg) { + for (;;) { + int sock = *(int *) arg; + char* buf = nullptr; + char* name = nullptr; + time_t time; + int res = readFix(sock, &buf, &name, &time, 0); + if (res <= 0) { + perror("Error while receiving:"); + exit(1); + } + time -= timezone; + printf("%s\t%10s:\t%s\n", ctime(&time),name,buf); + free(buf); + free(name); + } +} +int main( int argc, char** argv) { + tzset(); + char* addr; + int port; + char* readbuf; + if(argc <3) { + printf("Using default port %d\n",DEF_PORT); + port = DEF_PORT; + } else + port = atoi(argv[2]); + if(argc < 2) { + printf("Using default addr %s\n",DEF_IP); + addr = DEF_IP; + } else + addr = argv[1]; + // создаем сокет + struct sockaddr_in peer; + peer.sin_family = AF_INET; + peer.sin_port = htons( port ); + peer.sin_addr.s_addr = inet_addr( addr ); + int sock = socket( AF_INET, SOCK_STREAM, 0 ); + if ( sock < 0 ){ + perror( "Can't create socket\n" ); + exit( 1 ); + } + // присоединяемся к серверу + int res = connect( sock, ( struct sockaddr * )&peer, sizeof(peer ) ); + if (res) { + perror( "Can't connect to server:" ); + exit( 1 ); + } + // основной цикл программы + char buf[100]; + char name[20]; + printf("Enter your name\n"); + bzero(name, 20); + fgets(name, 20, stdin); + name[strlen(name)-1] = '\0'; + pthread_t thr; + res = pthread_create(&thr,NULL,reader,(void*)&sock); + if (res) { + printf("Error while creating new thread\n"); + } + for(;;) { + printf("Input request (empty to exit)\n"); + bzero(buf,100); + fgets(buf, 100, stdin); + buf[strlen(buf)-1] = '\0'; + if(strlen(buf) == 0) { + printf("Bye-bye\n"); + return 0; + } + res = sendFix(sock, buf, name, 0); + if ( res <= 0 ) { + perror( "Error while sending:" ); + exit( 1 ); + } + + } +} +int readFix(int sock, char** buf, char** name, long* time, int flags) { + // читаем "заголовок" - сколько байт составляет наше сообщение + unsigned msgLength = 0; + unsigned nameLength = 0; + int res=recv(sock,&msgLength,sizeof(unsigned),flags|MSG_WAITALL); + if (res <= 0)return res; + // читаем само сообщение + *buf = new char[msgLength+1]; + bzero(*buf, msgLength+1); + res = recv(sock, *buf, msgLength, flags | MSG_WAITALL); + if (res <= 0) return res; + res = recv(sock, &nameLength, sizeof(unsigned), flags | MSG_WAITALL); + if (res <= 0) return res; + *name = new char[nameLength+1]; + bzero(*name, nameLength+1); + res = recv(sock, *name, nameLength, flags | MSG_WAITALL); + if (res <= 0) return res; + res = recv(sock, time, sizeof(long), flags | MSG_WAITALL); + if (res <= 0) return res; + return 1; +} +int sendFix(int sock, char* buf, char* name, int flags) { + // число байт в сообщении + unsigned msgLength = strlen(buf); + unsigned nameLength = strlen(name); + int res = send(sock, &msgLength, sizeof(unsigned), flags ); + if (res <= 0) return res; + res = send(sock, buf, msgLength, flags); + if (res <= 0) return res; + res = send(sock, &nameLength, sizeof(unsigned), flags); + if (res <= 0) return res; + res = send(sock, name, nameLength, flags); + if (res <= 0) return res; + return 1; +} diff --git a/src/server.cpp b/src/server.cpp new file mode 100644 index 00000000..5a1ed91c --- /dev/null +++ b/src/server.cpp @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#define DEF_PORT 8888 +#define DEF_IP "127.0.0.1" +std::set clients; +// обработка одного клиента +int readFix(int sock, char** msg, char** name, long* time, int flags); +int sendFix(int sock, char* buf, char* name, long* time, int flags); +void* clientHandler(void* args) { + int sock = *(int*)args; + char* buf = nullptr; + char* name = nullptr; + int res = 0; + for(;;) { + long time; + res = readFix(sock, &buf,&name, &time, 0); + if ( res <= 0 ) { + perror( "Can't recv data from client, ending thread\n" ); + clients.erase(sock); + pthread_exit(nullptr); + } + printf("%s\t%10s:%s\n",ctime(&time),name,buf); + for (auto it = clients.begin(); it != clients.end(); it++) { + res = sendFix(*it, buf,name,&time, 0); + if (res <= 0) { + perror("send call failed"); + clients.erase(sock); + pthread_exit(nullptr); + } + } + free(name); + free(buf); + } +} +void* main_cycle(void* args) { + int listener = *(int*)args; + for(;;) { + int client = accept(listener, nullptr, nullptr ); + pthread_t thrd; + int res = pthread_create(&thrd, nullptr, clientHandler, (void*)(&client)); + if (res){ + printf("Error while creating new thread\n"); + break; + } + clients.insert(client); + } +} +int main( int argc, char** argv) { + int port = 0; + if(argc < 2) { + printf("Using default port %d\n",DEF_PORT); + port = DEF_PORT; + } else + port = atoi(argv[1]); + struct sockaddr_in listenerInfo; + listenerInfo.sin_family = AF_INET; + listenerInfo.sin_port = htons( port ); + listenerInfo.sin_addr.s_addr = htonl( INADDR_ANY ); + int listener = socket(AF_INET, SOCK_STREAM, 0 ); + if ( listener < 0 ) { + perror( "Can't create socket to listen: " ); + exit(1); + } + int res = bind(listener,(struct sockaddr *)&listenerInfo, sizeof(listenerInfo)); + if ( res < 0 ) { + perror( "Can't bind socket" ); + exit( 1 ); + } + // слушаем входящие соединения + res = listen(listener,5); + if (res) { + perror("Error while listening:"); + exit(1); + } + // основной цикл работы + pthread_t cycle; + res = pthread_create(&cycle, nullptr, main_cycle, (void*)(&listener)); + if (res){ + printf("Error while creating new thread\n"); + } + char input; + for(;;) { + input = (char)getchar(); + if (input == 'q') { + exit(0); + } + } +} +int readFix(int sock, char** msg, char** name, long* time, int flags) { + // читаем "заголовок" - сколько байт составляет наше сообщение + unsigned msgLength = 0; + unsigned nameLength = 0; + struct tm *t; + int res=recv(sock,&msgLength,sizeof(unsigned),flags|MSG_WAITALL ); + if (res <= 0)return res; + // читаем само сообщение + *msg = new char[msgLength+1]; + bzero(*msg, msgLength+1); + res = recv(sock, *msg, msgLength, flags | MSG_WAITALL); + if (res <= 0) return res; + res = recv(sock,&nameLength, sizeof(unsigned), flags|MSG_WAITALL); + if (res <= 0) return res; + *name= new char[nameLength+1]; + bzero(*name, nameLength+1); + res = recv(sock, *name, nameLength, flags|MSG_WAITALL); + if (res <= 0) return res; + *time = ::time(nullptr); + t = gmtime(time); + *time = mktime(t); + return 1; +} +int sendFix(int sock, char* buf, char* name, long* time, int flags) { + // шлем число байт в сообщении + unsigned msgLength = strlen(buf); + unsigned nameLength = strlen(name); + int res = send(sock, &msgLength, sizeof(unsigned), flags ); + if (res <= 0) return res; + res = send(sock, buf, msgLength, flags); + if (res <= 0) return res; + res = send(sock, &nameLength, sizeof(unsigned), flags); + if (res <= 0) return res; + res = send(sock, name, nameLength, flags); + if (res <= 0) return res; + res = send(sock, time, sizeof(long), flags); + if (res <= 0) return res; + return 1; +}