Here is a simple diagram which shows how sockets work:
Here is a header file Channel.h of the channel class which encapsulates socket:
#ifndef LAB_CHANNEL #define LAB_CHANNEL #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> namespace lab { class Channel { int socket_id; sockaddr_in socket_address; void CreateSocket(const char* ip, int port); void Write(int connection_id, const char* message); void Read(int connection_id); public: Channel(const char* ip, int port); ~Channel(); void Listen(); void Send(const char *message); void Close(); }; } #endifHere is a source file Channel.cpp of the Channel class:
#include "Channel.h" #include <iostream> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> lab::Channel::Channel(const char* ip, int port) { this->CreateSocket(ip, port); } lab::Channel::~Channel() { this->Close(); } void lab::Channel::CreateSocket(const char* ip, int port) { // socket() creates an endpoint for communication and returns a descriptor. // AF_INET - IPv4 Internet protocols. // SOCK_STREAM - Provides sequenced, reliable, two-way, connection-based byte // streams. socket_id = socket(AF_INET, SOCK_STREAM, 0); if (socket_id == -1) { std::cout << "Failed to create socket." << std::endl; } else { std::cout << "Socket was created successfully." << std::endl; } socket_address.sin_family = AF_INET; socket_address.sin_port = htons(port); socket_address.sin_addr.s_addr = inet_addr(ip); memset(&(socket_address.sin_zero), 0, 8); // bind - bind a name to a socket. if (bind(socket_id, (struct sockaddr *)&socket_address, sizeof(struct sockaddr)) != -1) { std::cout << "Name was binded successfully to the socket." << std::endl; } else { std::cout << "Failed to bind a name to the socket." << std::endl; } } void lab::Channel::Write(int connection_id, const char* message) { if (write(connection_id, message, strlen(message)) != -1) { std::cout << "Message was send: " << message << std::endl; } else { std::cout << "Failed to send a message." << std::endl; } } void lab::Channel::Read(int connection_id) { char buffer[32]; memset(buffer, 0, 32); if (read(connection_id, buffer, 32) != -1) { std::cout << "Message was read: " << buffer << std::endl; } else { std::cout << "Failed to read a message." << std::endl; } } void lab::Channel::Listen() { // listen - listen for connections on a socket. // The backlog argument defines the maximum length to which the queue of // pending connections for sockfd may grow. if (listen(socket_id, 4) != -1) { std::cout << "Listening the socket." << std::endl; } else { std::cout << "Failed to listen the socket." << std::endl; } // accept - accept a connection on a socket. sockaddr_in remote_address; int connection_id; int remote_address_size = sizeof(remote_address); connection_id = accept(socket_id, (sockaddr*)&remote_address, (socklen_t*)&remote_address_size); if (connection_id != -1) { std::cout << "Connection was accepted." << std::endl; } else { std::cout << "Failed to accept connection." << std::endl; } this->Read(connection_id); this->Write(connection_id, "Reply"); close(connection_id); } void lab::Channel::Send(const char *message) { // connect - initiate a connection on a socket. if (connect(socket_id, (sockaddr*)&socket_address, sizeof(sockaddr)) != -1) { std::cout << "Connection was estableshed successfully." << std::endl; } else { std::cout << "Failed to connect." << std::endl; } this->Write(socket_id, message); this->Read(socket_id); } void lab::Channel::Close() { close(socket_id); }Here is a file Client.cpp of the client application:
#include <iostream> #include "Channel.h" int main() { std::cout << "Client started..." << std::endl; lab::Channel *channel = new lab::Channel("127.0.0.1", 2590); channel->Send("Request"); delete channel; return 0; }Here is a file Server.cpp of the client application:
#include <iostream> #include "Channel.h" int main() { std::cout << "Service started..." << std::endl; lab::Channel *channel = new lab::Channel("127.0.0.1", 2590); channel->Listen(); delete channel; return 0; }Also I added makefile which allows to compile source code:
CPP = g++ CFLAGS = -Wall -lrt CHANNEL_FILES = src/Channel.cpp SERVICE_FILES = src/Service.cpp CLIENT_FILES = src/Client.cpp all: service client service: channel $(SERVICE_FILES) $(CPP) $(CFLAGS) -o bin/service obj/channel.o $(SERVICE_FILES) client: channel $(CLIENT_FILES) $(CPP) $(CFLAGS) -o bin/client obj/channel.o $(CLIENT_FILES) channel: $(CHANNEL_FILES) $(CPP) $(CFlAGS) -o obj/channel.o -c $(CHANNEL_FILES) clean: rm -f ./obj/*.o rm -f ./bin/service rm -f ./bin/client run-service: ./bin/service run-client: ./bin/client
No comments:
Post a Comment