I'm having an issue with my code, I'm trying to create an HTTP server using C++ 98 on MacOS, and I'm expecting the block of read to be executed before the write one, but the opposite is happening and I don't know why.
So I'm expecting to read first the request, then send a response. but the opposite is happening here,
this my code:
/************************ CONSTRUCTORS/DESTRUCTOR ************************/
webserv::Server::Server(int addr, int port)
{
this->sock.create_socket(AF_INET, SOCK_STREAM, 0);
this->sock.bind_socket(addr, port);
this->sock.listen_socket(__MAX_BACKLOG__);
}
webserv::Server::~Server() {}
/************************ MEMBER FUNCTION ************************/
void webserv::Server::lunch()
{
this->kq.create_event(this->sock.getSocket(), EVFILT_READ);
while (1)
this->_lunch_worker();
}
void webserv::Server::_lunch_worker(void)
{
int ev_count = this->kq.get_event();
static const char* index_html = "HTTP/1.0 200 OK\r\n" \
"Content-Length: 86\r\n\r\n" \
"<!DOCTYPE html>" \
"<html><head>Hello, world!</head><body><h1>cdn-ish...</h1></body></html>\r\n";
char buf[10000];
for (int i = 0; i < ev_count; i++) {
int fd = this->kq.get_fd(i);
if (fd < 0) continue;
if (fd == this->sock.getSocket()) {
int clientaddr_size = sizeof(this->sock.getAddress());
int clientfd = this->sock.accept_socket();
if (clientfd < 0) {
perror("accept");
close(fd);
return ;
}
this->kq.create_event(clientfd, EVFILT_READ);
if (fcntl(clientfd, F_SETFL, O_NONBLOCK) < 0) {
perror("fcntl");
close(clientfd);
close(fd);
}
this->kq.create_event(clientfd, EVFILT_WRITE, EV_ADD | EV_ONESHOT);
// EXPECTING THIS BLOCK TO BE CHECKED/EXECUTED FIRST
// BUT INSTEAD THE NEXT BLOCK (WRITE BLOCK) IS EXECUTED FIRST
// THEN IN THE SECOND ITERATION THE READ BLOCK IS BEING EXECUTED
} else if (this->kq.is_read_available(i)) {
int len;
std::cout << "READ" << std::endl;
// memset(buf, 0, sizeof(buf));
if ((len = recv(fd, buf, sizeof(buf), 0)) == 0) {
std::cout << "READ: FD CLOSED = " << fd << std::endl;
close(fd);
}
else if (len > 0)
{
}
std::cout << "READ: LEN = " << len << std::endl;
} else if (this->kq.is_write_available(i)) {
int len = 0;
if ((len = send(fd, index_html, strlen(index_html), 0)) != 0) {
}
std::cout << "WRITE: LEN = " << len << std::endl;
}
}
}
and kqueue class:
/***********************************************************************
* FILENAME : Kqueue.cpp
*
* DESCRIPTION :
* This File is the implementation of the functions
* Defined in Kqueue.hpp
*
**/
# include "./Kqueue.hpp"
# include "../../OutputColors.hpp"
/************************ CONSTRUCTORS/DESTRUCTOR ************************/
webserv::Kqueue::Kqueue()
{
this->_kq = kqueue();
std::cout << "KQUEUE CREATED" << std::endl;
this->test_error(this->_kq, "Creating Kqueue :");
this->_n_ev = 0;
}
webserv::Kqueue::~Kqueue()
{
close(this->_kq);
}
/************************ MEMBER FUNCTIONS ************************/
void webserv::Kqueue::set_event(int fd, int filter, int flags, void *udata)
{
EV_SET(&this->_ev_set, fd, filter, flags, 0, 0, udata);
}
void webserv::Kqueue::add_event(void)
{
int ret;
ret = kevent(this->_kq, &this->_ev_set, 1, NULL, 0, NULL);
this->test_error(ret, "Kqueue/add_even functions");
}
int webserv::Kqueue::get_event(void)
{
this->_n_ev = kevent(this->_kq, NULL, 0, this->_ev_list, __EV_LIST_SIZE__, NULL);
this->test_error(this->_n_ev, "Kqueue/get_event function:");
return (this->_n_ev);
}
void webserv::Kqueue::create_event(int fd, int filter, int flags, void *udata)
{
this->set_event(fd, filter, flags, udata);
this->add_event();
}
bool webserv::Kqueue::isEOF(int index)
{
if (this->_n_ev <= index)
this->test_error(-1, "Kqueue/isEOF function:");
return (this->_ev_list[index].flags & EV_EOF);
}
bool webserv::Kqueue::is_read_available(int index)
{
if (this->_n_ev <= index)
this->test_error(-1, "Kqueue/is_read_available function:");
return (this->_ev_list[index].filter == EVFILT_READ);
}
bool webserv::Kqueue::is_write_available(int index)
{
if (this->_n_ev <= index)
this->test_error(-1, "Kqueue/is_write_available function:");
return (this->_ev_list[index].filter == EVFILT_WRITE);
}
void webserv::Kqueue::test_error(int fd, const std::string &str)
{
if (fd < 0)
{
std::cerr << RED << str << " ";
perror("The following error occured: ");
std::cerr << RESET;
exit(EXIT_FAILURE);
}
}
/************************ GETTERS/SETTERS ************************/
struct kevent *webserv::Kqueue::get_event_list()
{
return (this->_ev_list);
}
int &webserv::Kqueue::get_kq()
{
return (this->_kq);
}
int webserv::Kqueue::get_fd(int index)
{
if (this->_n_ev <= index)
this->test_error(-1, "Kqueue/get_ev_list function:");
return (this->_ev_list[index].ident);
}
void webserv::Kqueue::set_kqueue(int fd)
{
this->_kq = fd;
}
Does anyone know why the WRITE comes before the READ in my case, I'm expecting to read the request, then sending the response
In order for it to be possible to read from the socket, first the other side has to detect that the connection is complete, then it has to compose its query and put it on the wire. Then your side has to receive the information and process it. Only then it is possible to read from the socket.
In order for it to be possible to write to the socket, you have to detect that the connection is complete. That's it. If the connection is complete, it's possible to write.
It's not surprising that it's possbile to write to the socket before it's possible to read from it. The question is -- why is your code checking if it's possible to write to the socket when you don't want to write to the socket? Also, why does your code write to the socket just because it's possible to do so even when you haven't even received a query from the other side?
If you have no data to write to the other side because you haven't even received a query from the other side yet, why are you checking whether or not it's possible to write on the socket? You don't want to write even if it's possible, so why check?
Related
I got several numbers from user by single linked list and my program's task is finding the smallest and largest number in the linked list by two classes and print them on the sreen. But after a time, my program got closed and i didn't see anything. What went wrong?
#include<iostream>
using namespace std;
struct Node
{
double Number;
struct Node *Point;
} *End = nullptr;
typedef struct Node node;
namespace Min_Max
{
class Min
{
node *Result = End;
public: Min()
{
if(Result == nullptr)
{
cout << "You didn\'t enter anything!\a";
system("pause");
exit(EXIT_FAILURE);
}
node *Counter = Result->Point;
while(Counter != nullptr)
{
if(Counter->Number < Result->Number)
Result = Counter;
Result = Result->Point;
}
}
node* Show()
{
return Result;
}
};
class Max
{
private:
node *Result = End;
public:
Max()
{
if(Result == nullptr)
{
cout << "You didn\'t enter anything!\a";
system("pause");
exit(EXIT_FAILURE);
}
node *Counter = Result->Point;
while(Counter != nullptr)
{
if(Counter->Number > Result->Number)
Result = Counter;
Result = Result->Point;
}
}
node* Show()
{
return Result;
}
};
};
int main()
{
node *linker = nullptr;
register short int Counter = 1;
while(1)
{
linker = new node;
if(linker == nullptr)
{
cout << "An error occurred during allocating memory." << endl << endl;
system("pause");
return 0;
}
cout << "Number " << Counter << ": Enter your number: ";
cin >> linker->Number;
system("cls");
if(linker->Number == 0)
{
delete linker;
break;
}
linker->Point = End;
End = linker;
Counter++;
}
Min_Max::Min Min;
Min_Max::Max Max;
cout << "The smallest number is " << (Min.Show())->Number << endl;
cout << "The largest number is " << (Max.Show())->Number << endl;
return 0;
}
My C++ compiler is GCC-C++11 and my operating system is Windows 10.
I'm working on a simple async socket client built on top of winsock with io completion ports
it sometimes works and sometimes blocks with strange behaviours
this is the design of the async process :
there are global iocp threads running to receive the completion packets and notify submitters
the submitters use QueueUserApc routine to make the io call in the context of one of the waiting thread
the apc routine makes the async io call and the the a waiter thread should receive the result and notify the issuer
this is my simple wrapper for the io completion ports
template <class T, auto CloseFn>
struct HandleDeleter
{
using pointer = T;
void operator ()(pointer handle) { CloseFn(handle); }
};
using Handle = std::unique_ptr<void, HandleDeleter<HANDLE, CloseHandle>>;
struct IoContext : public OVERLAPPED
{
IoContext()
{
memset(this, 0, sizeof(OVERLAPPED));
}
};
struct CompletionResult
{
CompletionResult() : BytesTransferred(0), Key(0), Ctx(nullptr) {}
CompletionResult(unsigned long bytes, uintptr_t key, IoContext* ctx) : BytesTransferred(bytes), Key(key), Ctx(ctx) {}
unsigned long BytesTransferred;
uintptr_t Key;
IoContext *Ctx;
};
class IoPort
{
Handle port_handle;
public:
IoPort()
{}
IoPort(Handle&& port) : port_handle(std::move(port))
{}
IoPort(IoPort&& rhs) : port_handle(std::move(rhs.port_handle))
{}
IoPort& operator=(IoPort&& rhs)
{
port_handle = std::move(rhs.port_handle);
return *this;
}
bool Create(unsigned int max_threads = 0);
bool AddToPort(Handle& file, uintptr_t key);
bool AddToPort(SOCKET sock, uintptr_t key);
bool GetResultOrApc(CompletionResult& result, DWORD WaitTimeMs);
void Close()
{
port_handle.reset();
}
};
bool IoPort::Create(unsigned int max_threads)
{
port_handle.reset(CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, max_threads));
return bool(port_handle);
}
bool IoPort::AddToPort(Handle & file, uintptr_t key)
{
return CreateIoCompletionPort(file.get(), port_handle.get(), key, 0) != nullptr;
}
bool IoPort::AddToPort(SOCKET sock, uintptr_t key)
{
return CreateIoCompletionPort((HANDLE)sock, port_handle.get(), key, 0) != nullptr;
}
bool IoPort::GetResultOrApc(CompletionResult & result, DWORD WaitTimeMs)
{
OVERLAPPED_ENTRY entry = { 0 };
DWORD count = 0;
BOOL wait_result = GetQueuedCompletionStatusEx(port_handle.get(), &entry, 1, &count, WaitTimeMs, TRUE);
if (entry.lpOverlapped)
{
result.Key = entry.lpCompletionKey;
result.BytesTransferred = entry.dwNumberOfBytesTransferred;
result.Ctx = (IoContext*)entry.lpOverlapped;
}
return wait_result;
}
then this is the global iocp threads that starts before entering main function
struct IOCPThreads
{
iocp::IoPort Port;
std::vector<std::thread> IoThreads;
bool Exit = false;
IOCPThreads()
{
if (!Port.Create())
std::cout << "[!] failed to open the port , error : " << GetLastError() << std::endl;
auto num = std::thread::hardware_concurrency();
IoThreads.reserve(num);
std::stringstream thd_ids;
thd_ids << "threads ids : { ";
for (auto i : range(0u, num))
{
IoThreads.emplace_back(std::thread(&IOCPThreads::IoThread, this));
thd_ids << IoThreads[i].get_id() << ", ";
}
auto str = thd_ids.str();
str.pop_back();
str.pop_back();
str += " }";
std::cout << str << std::endl;
}
~IOCPThreads()
{
Exit = true;
for (auto& thd : IoThreads)
if (thd.joinable())
thd.join();
}
void IoThread()
{
while (!Exit)
{
iocp::CompletionResult result;
Port.GetResultOrApc(result, 10);
if (GetLastError() == WAIT_IO_COMPLETION)
std::cout << "[*] received an apc" << std::endl; // sometimes print and sometimes no
if (!result.Ctx)
continue;
DWORD transeferred, Flags;
std::unique_ptr<ClientIoCtx> ctx((ClientIoCtx*)result.Ctx);
WSAGetOverlappedResult(ctx->sock->GetHandle().get(), ctx.get(), &transeferred, FALSE, &Flags);
int WsaError = WSAGetLastError();
if (ctx->op == ClientIoOp::Recv)
{
std::unique_ptr<ClientIoRecvCtx> RecvCtx = unique_static_cast<ClientIoRecvCtx>(ctx);
RecvCtx->OnResult(*RecvCtx->sock, WsaError, std::span{ RecvCtx->buffer, RecvCtx->buffer + RecvCtx->length }, transeferred);
}
}
}
};
IOCPThreads ClientIoThreads;
and this is the socket implemention :
enum class async_status_code : unsigned int
{
Pending,
Finished,
Error,
};
struct AsyncResult
{
async_status_code code;
unsigned int transferred;
AsyncResult() : code(async_status_code::Error), transferred(0)
{}
AsyncResult(async_status_code c, unsigned int s) : code(c), transferred(s)
{}
bool IsPending() const
{
return code == async_status_code::Pending;
}
bool IsFinished() const
{
return code == async_status_code::Finished;
}
bool IsFailed() const
{
return code == async_status_code::Error;
}
};
using AsyncSendFunc = std::function<void(Socket& sock, int ErrorCode, std::span<const char> Buffer, DWORD transeferred)>;
enum class SendRecvFlags
{
UnSpecefied = 0,
MsgDontRoute = 0x4,
MsgOOB = 0x1,
MsgPeek = 0x2,
MsgWaitAll = 0x8,
MsgPushImmediate = 0x20,
};
enum class ClientIoOp
{
Send,
};
struct ApcResult
{
async_status_code code;
DWORD transeferred;
int error;
};
struct ClientIoCtx : public IoContext
{
Socket *sock;
ClientIoOp op;
promise<ApcResult> notifier;
};
struct ClientIoSendCtx : public ClientIoCtx
{
ClientIoSendCtx() { op = ClientIoOp::Send; }
const char *buffer;
int length;
SendRecvFlags flags;
AsyncSendFunc OnResult;
};
AsyncResult LIB_NAMESPACE::net::Socket::AsyncSend(const char * buffer, int length, io::IoContext & IoCtx, SendRecvFlags flags)
{
WSABUF buff_vec{ length, (char*)buffer };
DWORD sent = 0;
if (WSASend(sock.get(), &buff_vec, 1, &sent, (DWORD)flags, &IoCtx, nullptr) == 0)
return AsyncResult(async_status_code::Finished, sent);
else if (WSAGetLastError() == WSA_IO_PENDING)
return AsyncResult(async_status_code::Pending, sent);
return AsyncResult();
}
AsyncResult LIB_NAMESPACE::net::Socket::AsyncSend(const char * buffer, int length, const AsyncSendFunc & OnSend, SendRecvFlags flags)
{
ClientIoSendCtx *ctx = new ClientIoSendCtx();
ctx->sock = this;
ctx->buffer = buffer;
ctx->length = length;
ctx->flags = flags;
ctx->OnResult = OnSend;
auto fut = ctx->notifier.get_future(); // notifier is a promise
auto& thd = ClientIoThreads.IoThreads[RandomUInt(0, ClientIoThreads.IoThreads.size() - 1)];
std::cout << "[*] launchin the apc routine in thread : " << thd.get_id() << std::endl; // it's always one of the io threads
auto dwRes = QueueUserAPC(Socket::ApcRoutine, thd.native_handle(), (ULONG_PTR)ctx);
if (!dwRes) // doesn't happen
{
delete ctx;
std::cout << "QueueUserAPC failed with error " << GetLastError() << std::endl;
return AsyncResult();
}
auto result = fut.get(); // --> blocks here because the apc routine doesn't start
WSASetLastError(result.error); // the wsa error is thread local so I transfer it from the apc thread to this thread
return AsyncResult(result.code, result.transeferred);
}
void ApcRoutine(unsigned long long Param)
{
std::cout << "[*] ApcRoutine started" << std::endl; // sometimes is printed and sometimes no
std::unique_ptr<ClientIoCtx> ctx((ClientIoCtx*)Param);
if (ctx->op == ClientIoOp::Send)
{
std::unique_ptr<ClientIoSendCtx> SendCtx = unique_static_cast<ClientIoSendCtx>(ctx);
auto async_result = SendCtx->sock->AsyncSend(SendCtx->buffer, SendCtx->length, *SendCtx, SendCtx->flags);
ApcResult apc_result;
apc_result.code = async_result.code;
apc_result.transeferred = async_result.transferred;
apc_result.error = WSAGetLastError();
SendCtx->notifier.set_value(apc_result);
if (apc_result.code != async_status_code::Error)
SendCtx.release();
}
}
the problem is that the QueuUserApc sometimes doesn't fail but the apc routine doesn't start so the the issuer thread blocks waiting with future::get
I checked the GetLasError() value every time after calling QueuUserApc and it is always 0 so what is wrong here ?
I'm totally new in developing, so I understand that my code can be absolutely incorrect. But I have a problem with connecting the second client in the server. I've found bug with accept function. When I try to connect the second client my program stops work, server waiting to data from second client, but I can't send data. I've tried to use WSAGetLastError(), but it returns 0. Please, help me.
It's my server:
# include <iostream>
# include <WinSock2.h>
# pragma comment(lib,"ws2_32.lib")
class tictac {
char garr[10];
public:
tictac() {garr[0]='0'; for(int i=0; i<10;++i){garr[i]=garr[0]+i;}}
void move(int turn, char field_change) {
garr[turn]=field_change;
}
char chack(int chack) {
if(garr[chack]=='O'||garr[chack]=='X') {
return 'B';
} else {
return 'U';
}
}
} ;
class play {
tictac OurGame;
SOCKADDR_IN playerTurn1;
SOCKADDR_IN playerTurn2;
SOCKET playerSock1;
SOCKET playerSock2;
public:
int play1(){
WSAData game_one;
if((WSAStartup(MAKEWORD(2,2), &game_one))!=0) {
std::cout<<"Filed to init socket library. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 1;
}
SOCKET serverSocket = socket(2,1,6);
if(serverSocket==INVALID_SOCKET) {
std::cout<<"Fail to create socket. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 2;
}
SOCKADDR_IN serverGame;
serverGame.sin_family=2;
serverGame.sin_port=htons(4324);
serverGame.sin_addr.s_addr=INADDR_ANY;
if(bind(serverSocket, (sockaddr*)&serverGame,sizeof(serverGame))!=0) {
std::cout<<"Fail to bind socket. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 3;
}
listen(serverSocket, 5);
///////////////////////////////////////////////////////////////////////////////////////////////////
playerTurn1;
serverGame.sin_family=2;
serverGame.sin_port=htons(4324);
serverGame.sin_addr.s_addr=inet_addr("127.0.0.1");
//////////////////////////////////////////////////////////////////////////////////////////////////
int size1=sizeof(playerTurn1);
playerSock1 = accept(serverSocket, (sockaddr*)& playerTurn1, &size1); // Socket of first player
if(playerSock1==INVALID_SOCKET) {
std::cout<<"Failed accept with player 1. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 4;
}
char msg[2]="y";
int turn;
while(msg[0]!='Y'){
// ================================= ******* ******* ****** Turn of player one
recv(playerSock1, msg, 2, 0);
std::cout<<msg[0]<<std::endl;
turn=atoi(&msg[0]);
if(turn==0||OurGame.chack(turn)=='B') {
msg[0]='N';
send(playerSock1, msg, 2, 0);
std::cout<<"fail"<<std::endl;
} else {
msg[0]='Y';
OurGame.move(turn, 'X');
send(playerSock1, msg, 2, 0);
}
}
if(closesocket(serverSocket)==SOCKET_ERROR) {std::cout<<"ERROR With closing server socket !"<<std::endl; }
if(closesocket(playerSock1)==SOCKET_ERROR) { std::cout<<"ERROR With closing player's socket !"<<std::endl;}
system ("pause");
WSACleanup();
}
int play2() {
WSAData game_two;
if((WSAStartup(MAKEWORD(2,2), &game_two))!=0) {
std::cout<<"Filed to init socket library. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 1;
}
SOCKET serverSocket = socket(2,1,6);
if(serverSocket==INVALID_SOCKET) {
std::cout<<"Fail to create socket. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 2;
}
SOCKADDR_IN serverGame;
serverGame.sin_family=2;
serverGame.sin_port=htons(4324);
serverGame.sin_addr.s_addr=INADDR_ANY;
if(bind(serverSocket, (sockaddr*)&serverGame,sizeof(serverGame))!=0) {
std::cout<<"Fail to bind socket. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 3;
}
listen(serverSocket, 5);
///////////////////////////////////////////////////////////////////////////////////////////////////
playerTurn2;
serverGame.sin_family=2;
serverGame.sin_port=htons(4324);
serverGame.sin_addr.s_addr=inet_addr("127.0.0.1");
//////////////////////////////////////////////////////////////////////////////////////////////////
int size2=sizeof(playerTurn2);
playerSock1 = accept(serverSocket, (sockaddr*)& playerTurn1, &size2); // Socket of second player
std::cout<<"I beg of you, say me something!"<<std::endl; system ("pause");
if(playerSock1==INVALID_SOCKET) {
std::cout<<"Failed accept with player 1. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 4;
}
char msg[2]="y";
int turn;
while(msg[0]!='Y'){
// ================================= ******* ******* ****** Turn of player one
recv(playerSock1, msg, 2, 0);
std::cout<<msg[0]<<std::endl;
turn=atoi(&msg[0]);
if(turn==0||OurGame.chack(turn)=='B') {
msg[0]='N';
send(playerSock1, msg, 2, 0);
std::cout<<"fail"<<std::endl;
} else {
msg[0]='Y';
OurGame.move(turn, 'X');
send(playerSock1, msg, 2, 0);
}
}
if(closesocket(serverSocket)==SOCKET_ERROR) {std::cout<<"ERROR With closing server socket !"<<std::endl; }
if(closesocket(playerSock1)==SOCKET_ERROR) { std::cout<<"ERROR With closing player's socket !"<<std::endl;}
system ("pause");
WSACleanup();
}
} ;
int main() {
play PlayGame;
int queue=0;
while(true){
if(queue%2==0){
std::cout<<"first player"<<std::endl;
PlayGame.play1();
++queue;
} else {
std::cout<<"Second player"<<std::endl;
PlayGame.play2();
++queue;
}
}
}
It's my first client:
# include <iostream>
# include <WinSock2.h>
# pragma comment(lib,"ws2_32.lib")
class Game {
char cell[9];
public:
Game() {cell[0]='1'; for(int i=0; i<9; ++i){cell[i]=cell[0]+i;}}
void board() { // ==================== ======================= * * * This method just prints start game board
char table[3][3];
int index=0;
std::cout<<" GAME BOARD"<<std::endl<<std::endl;
std::cout<<"Player 1 you use X"<<std::endl;
std::cout<<"Player 2 you use O"<<std::endl<<std::endl;
for(int i=0; i<3; ++i) {
std::cout<<" ";
for(int j=0; j<3; ++j) {
table[i][j]=cell[index];
if(index!=2&&index!=5&&index!=8){
std::cout<<table[i][j]<<" | ";
} else {
std::cout<<table[i][j];
}
++index;
}
std::cout<<std::endl;
if(index<9){
std::cout<<" "<<"-----------"<<std::endl;
}
}
std::cout<<std::endl<<std::endl;
}
void change(int t) { // ========= ========= * * * This method helps user to fill field on the game board
system ("cls");
Game::cell;
cell[t-1]='X';
Game::board();
}
} ;
int main() {
// ================================================------------------_________ * * * Client
WSAData game;
if((WSAStartup(MAKEWORD(2,2), &game))!=0) {
std::cout<<"Filed to init socket library. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 1;
}
SOCKET serverSocket = socket(2,1,6);
if(serverSocket==INVALID_SOCKET) {
std::cout<<"Fail to create socket. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 2;
}
SOCKADDR_IN serverGame;
serverGame.sin_family=2;
serverGame.sin_port=htons(4324);
serverGame.sin_addr.s_addr=inet_addr("127.0.0.1");
if(connect(serverSocket, (sockaddr*)&serverGame,sizeof(serverGame))!=0) {
std::cout<<"Fail to connect socket. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 3;
}
// ===========================----------------------------------- ********** Try to send data !!!!!!!!!!!
// =========================== * * * Turn of player one
Game tic_tac_toe;
tic_tac_toe.board();
char msg[2]="n";
char field[1]; // ``````````````````````````````````````This variable exists to change field on the board
if(serverSocket==INVALID_SOCKET) {std::cout<<"Problem is here"<<std::endl; system ("pause");}
while(serverSocket!=INVALID_SOCKET){
std::cout<<"Chose field (enter number of field) : ";
start:
std::cin.getline(field, 3);
msg[0]=field[0]; std::cout<<atoi(&field[0])<<" "<<msg[0]<<std::endl;
send(serverSocket, msg, 2, 0);
recv(serverSocket, msg, 2, 0);
if(msg[0]=='N') {
std::cout<<"Error (!). Invalid input (!). Chose field again : ";
goto start;
} else if(msg[0]=='Y') {
system ("cls");
tic_tac_toe.change(atoi(&field[0]));
}
closesocket(serverSocket);
WSACleanup();
}
}
It's my second client
# include <iostream>
# include <WinSock2.h>
# pragma comment(lib,"ws2_32.lib")
class Game {
char cell[9];
public:
Game() {cell[0]='1'; for(int i=0; i<9; ++i){cell[i]=cell[0]+i;}}
void board() { // ==================== ======================= * * * This method just prints start game board
char table[3][3];
int index=0;
std::cout<<" GAME BOARD"<<std::endl<<std::endl;
std::cout<<"Player 1 you use X"<<std::endl;
std::cout<<"Player 2 you use O"<<std::endl<<std::endl;
for(int i=0; i<3; ++i) {
std::cout<<" ";
for(int j=0; j<3; ++j) {
table[i][j]=cell[index];
if(index!=2&&index!=5&&index!=8){
std::cout<<table[i][j]<<" | ";
} else {
std::cout<<table[i][j];
}
++index;
}
std::cout<<std::endl;
if(index<9){
std::cout<<" "<<"-----------"<<std::endl;
}
}
std::cout<<std::endl<<std::endl;
}
void change(int t) { // ========= ========= * * * This method helps user to fill field on the game board
system ("cls");
Game::cell;
cell[t-1]='O';
Game::board();
}
} ;
int main() {
// ================================================------------------_________ * * * Client
WSAData game;
if((WSAStartup(MAKEWORD(2,2), &game))!=0) {
std::cout<<"Filed to init socket library. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 1;
}
SOCKET serverSocket = socket(2,1,6);
if(serverSocket==INVALID_SOCKET) {
std::cout<<"Fail to create socket. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 2;
}
SOCKADDR_IN serverGame;
serverGame.sin_family=2;
serverGame.sin_port=htons(4324);
serverGame.sin_addr.s_addr=inet_addr("127.0.0.1");
if(connect(serverSocket, (sockaddr*)&serverGame,sizeof(serverGame))!=0) {
std::cout<<"Fail to connect socket. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 3;
}
// ===========================----------------------------------- ********** Try to send data !!!!!!!!!!!
// =========================== * * * Turn of player one
Game tic_tac_toe;
tic_tac_toe.board();
char msg[2]="n";
char field[2]; // ``````````````````````````````````````This variable exists to change field on the board
if(serverSocket==INVALID_SOCKET) {std::cout<<"Problem is here"<<std::endl;}
while(serverSocket!=INVALID_SOCKET){
std::cout<<"Chose field (enter number of field) : ";
while(msg[0]!='Y'){
std::cin.getline(field, 2);
msg[0]=field[0]; std::cout<<msg[0]; std::cin.get();
send(serverSocket, msg, 2, 0);
recv(serverSocket, msg, 2, 0);
if(msg[0]=='N') {
std::cout<<"Error (!). Invalid input (!). Chose field again : ";
} else if(msg[0]=='Y') {
system ("cls");
tic_tac_toe.change(atoi(&field[0]));
}
}
}
}
I've found my problem. I didn't understand how this connection works.
I am trying to make a socket program that lets two people chat. I have one thread for sending a message and another for receiving a message. When I use cin, it cuts off the first char that I input.
I've been looking at different threads here about cin and cout being tied and not being very thread safe, but nothing has worked.
Here is my send and receive threads:
RECV
char buffer[32];
while(true)
{
memset(&buffer, 0, sizeof(buffer));
unsigned long bytes_recv;
bytes_recv = recv(socketfd, &buffer, sizeof(buffer), 0);
if(bytes_recv == 0)
{
break;
}
for(unsigned long i = 0; i < bytes_recv; i++)
{
buffer[i] = buffer[i] ^ key;
}
printf("Message Received: %s\n", buffer);
}
and Send
char buffer[32];
int conn = 1;
while(true)
{
memset(buffer, 0, sizeof(buffer));
std::cout << "Send a message to host: ";
std::cin.clear();
std::cin.getline(buffer, sizeof(buffer));
std::cout << "StrLen: " << strlen(buffer) << std::endl;
for(unsigned long i = 0; i < strlen(buffer); i++)
{
std::cout << "Char: " << buffer[i] << std::endl;
buffer[i] = key ^ buffer[i];
}
conn = send(socketfd, &buffer, strlen(buffer), 0);
if(conn == -1)
{
break;
}
}
If I type "Hello", the buffer only reads "ello" even from the cin thread.
I am a beginner at the socket programming level that's why I found some problems that may be simple. I tried to send a simple message from client to server but the command send return (-1) that's why the message not received by the server.
Also, I have the same problem in the server code and the receiver command. return (-1).
Following is my client code :
bool ClientSock() {
int sock;
struct sockaddr_in address;
sock = socket(AF_INET, SOCK_STREAM, 0);
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_family = AF_INET;
address.sin_port = htons(10102);
if (connect(sock, (struct sockaddr*) &address, sizeof (address)) < 0) {
cout << "connect failed. Error \n";
return 0 ;
} else
return 1;
}
void SendComm() {
long ok;
char MESSAGE [2000];
string msg;
cout << "enter message:\t";
cin>> msg;
const char * s = msg.c_str();
int sock;
ok = send(sock, s, 1024, 0);`enter code here`
if ( send(sock,s,1024,0)< 0){//this is the problem
std::cout << "you can not send the message";
}
else{
ok = recv(sock, MESSAGE, sizeof (MESSAGE), 0);
string reply;
reply = MESSAGE;
cout << "server says:_t" << reply << endl;
}
}
int main() {
if (ClientSock()==1){
SendComm();
}
else
std::cout << "error";
}
This is my server code:
bool initialize() {
int conSock;
int ListenSock;
socklen_t addrsize;
struct sockaddr_in address;
addrsize = sizeof (address);
conSock = socket(AF_INET, SOCK_STREAM, 0);
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_family = AF_INET;
address.sin_port = htons(10102);
ListenSock = socket(AF_INET, SOCK_STREAM, 0);
bind(ListenSock, (sockaddr *) & address, sizeof (address));
listen(ListenSock, SOMAXCONN);
std::cout << "server waiting for connexion\n\n ";
if (conSock = accept(ListenSock, (struct sockaddr *) &address, &addrsize) < 0) {
cout << "connect failed. Error";
return 0;
} else
return 1;
}
void Communicate() {
int conSock;
int ListenSock;
struct sockaddr_in address;
socklen_t addrsize;
long ok;
char MESSAGE[2000];
ok = recv(conSock, MESSAGE, sizeof (MESSAGE), 0);
if (recv(conSock, MESSAGE, sizeof (MESSAGE), 0)< 0){
std:: cout << "No message" ;
}
else{
string msg;
msg = MESSAGE;
cout << " client says:\t" << msg << endl;
string reply;
cout << "enter reply:\t";
cin>> reply;
const char* s = reply.c_str();
ok = send(conSock, s, 1024, 0);
}}
int main() {
if (initialize() == 1) {
Communicate();
} else
std::cout << "error ";
}