How to use EPOLLONESHOT correctly? - c++

void modfd(const int& epollfd, const int& fd)
{
epoll_event event;
event.data.fd = fd;
event.events = EPOLLIN | EPOLLET | EPOLLONESHOT | EPOLLRDHUP;
epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &event);
}
void Worker::work()
{
while (true)
{
len = recv(connfd, temp, sizeof(temp), NULL);
if (len == -1 && errno == EAGAIN)
{
break;
}
else if (len == 0)
{
std::cout << "errno:" << errno << " " << connfd << std::endl;
//modfd(epollfd, connfd);
}
if (totle + len < sizeof(buf))
{
memcpy(buf + totle, temp, len);
totle += len;
}
}
//Should I register here?
modfd(epollfd, connfd);
}
If the above non-blocking and registered event functions have no errors, when should I use modFd?
To be precise, this problem only occurs in webbench. When I initiate the connection alone, the program seems to have no problem.

Related

Is there any implementation or how to implement `lockf()` for Windows?

I am porting some Linux code to Windows that uses lockf()
static string load_bulletin_from_file(const char* cache_filename)
{
int fd = open(cache_filename, O_RDWR); // lockf requires O_RDWR
if (fd == -1) {
etiLog.level(error) << "TAI-UTC bulletin open cache for reading: " <<
strerror(errno);
return "";
}
lseek(fd, 0, SEEK_SET);
vector<char> buf(1024);
vector<char> new_bulletin_data;
ssize_t ret = lockf(fd, F_LOCK, 0);
if (ret == 0) {
// exclusive lock acquired
do {
ret = read(fd, buf.data(), buf.size());
if (ret == -1) {
close(fd);
etiLog.level(error) << "TAI-UTC bulletin read cache: " <<
strerror(errno);
return "";
}
copy(buf.data(), buf.data() + ret, back_inserter(new_bulletin_data));
} while (ret > 0);
close(fd);
return string{new_bulletin_data.data(), new_bulletin_data.size()};
}
else {
etiLog.level(error) <<
"TAI-UTC bulletin acquire cache lock for reading: " <<
strerror(errno);
close(fd);
}
return "";
}
Since lockf() is a POSIX function, Windows does not have it so I don't really know is there a substitute or how to port this piece of code to Windows.

How to receive multiple files through TCP and save them at the same time in C++?

I'm trying to create an app which would accept many connections from clients at the same time and it works for me, but it also should download those files at the same time. In this version of server, even if clients are connected simultaneously, files are written one by one.
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <ctime>
#pragma comment(lib, "ws2_32.lib")
int main()
{
WSADATA wsaData;
int winsock_result = WSAStartup(MAKEWORD(2,2), &wsaData);
if(winsock_result != 0)
{
exit(1);
}
SOCKET server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(server_socket == INVALID_SOCKET)
{
WSACleanup();
exit(1);
}
int const max_clients = 100;
int client_socket[max_clients];
for (int i = 0; i < max_clients; i++)
{
client_socket[i] = 0;
}
char* ip_address = "127.0.0.1";
int port = 6666;
SOCKADDR_IN server;
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = inet_addr(ip_address);
int server_sizeof = sizeof(server);
int opt = TRUE;
if( setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0 )
{
closesocket(server_socket);
WSACleanup();
exit(1);
}
if(bind(server_socket,(SOCKADDR *)&server, server_sizeof) == SOCKET_ERROR)
{
closesocket(server_socket);
WSACleanup();
exit(1);
}
if(listen(server_socket, 5) == SOCKET_ERROR)
{
std::cout << "Nasluchiwanie portu nieudane." << std::endl;
}
else
{
std::cout << "Nasluchiwanie portu " << port << " udane." << std::endl << std::endl;
}
int const buffer_size = 512;
char buffer[buffer_size];
int max_socket_descriptor, socket_descriptor;
int downloaded_files = 1;
fd_set readfds;
while(true)
{
FD_ZERO(&readfds);
FD_SET(server_socket, &readfds);
max_socket_descriptor = server_socket;
for (int i = 0 ; i < max_clients ; i++)
{
socket_descriptor = client_socket[i];
if(socket_descriptor > 0)
{
FD_SET( socket_descriptor, &readfds);
}
if(socket_descriptor > max_socket_descriptor)
{
max_socket_descriptor = socket_descriptor;
}
}
if ((select( max_socket_descriptor + 1, &readfds, NULL, NULL, NULL) < 0) && (errno != EINTR))
{
std::cout << "Blad funkcji select." << std::endl;
}
if (FD_ISSET(server_socket, &readfds))
{
int new_sockfd;
if ((new_sockfd = accept(server_socket,(SOCKADDR *)&server, &server_sizeof)) == SOCKET_ERROR)
{
std::cout << "Otrzymanie deskryptora nieudane." << std::endl;
}
else
{
for (int i = 0; i < max_clients; i++)
{
if( client_socket[i] == 0 )
{
client_socket[i] = new_sockfd;
std::cout << "Dodawanie do listy socketow jako numer " << i << std::endl;
break;
}
}
}
}
for (int i = 0; i < max_clients; i++)
{
socket_descriptor = client_socket[i];
if (FD_ISSET( socket_descriptor, &readfds))
{
struct sockaddr_in client_address;
char filename[buffer_size];
std::stringstream ip_filename;
ip_filename << "plik" << downloaded_files << "_" << inet_ntoa(client_address.sin_addr);
strcpy(filename, ip_filename.str().c_str());
std::cout << "Nazwa pliku (IP klienta): " << filename << std::endl;
FILE* file;
file = fopen(filename, "wb");
const clock_t begin_time = clock();
int received_size;
do
{
memset(buffer, 0, buffer_size);
received_size = recv(socket_descriptor, buffer, buffer_size, 0);
if (received_size == 0 || received_size == -1)
{
break;
}
fwrite(buffer, sizeof(char), received_size, file);
}
while (received_size != 0);
fclose(file);
std::cout << "Czas wysylania pliku: " << float( clock () - begin_time ) / CLOCKS_PER_SEC << " sekund." << std::endl << std::endl;
closesocket(socket_descriptor);
client_socket[i] = 0;
downloaded_files++;
}
}
}
closesocket(server_socket);
WSACleanup();
system("pause");
return 0;
}
What should I do to make them write many at the same time? I've tried many modifications of the code above but every time I can't get wanted result.
For example:
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <ctime>
#pragma comment(lib, "ws2_32.lib")
int main()
{
WSADATA wsaData;
int winsock_result = WSAStartup(MAKEWORD(2,2), &wsaData);
if(winsock_result != 0)
{
exit(1);
}
SOCKET server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(server_socket == INVALID_SOCKET)
{
WSACleanup();
exit(1);
}
int const max_clients = 100;
int client_socket[max_clients];
for (int i = 0; i < max_clients; i++)
{
client_socket[i] = 0;
}
char* ip_address = "127.0.0.1";
int port = 6666;
SOCKADDR_IN server;
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = inet_addr(ip_address);
int server_sizeof = sizeof(server);
int opt = TRUE;
if( setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0 )
{
closesocket(server_socket);
WSACleanup();
exit(1);
}
if(bind(server_socket,(SOCKADDR *)&server, server_sizeof) == SOCKET_ERROR)
{
closesocket(server_socket);
WSACleanup();
exit(1);
}
if(listen(server_socket, 5) == SOCKET_ERROR)
{
std::cout << "Nasluchiwanie portu nieudane." << std::endl;
}
else
{
std::cout << "Nasluchiwanie portu " << port << " udane." << std::endl << std::endl;
}
int const buffer_size = 512;
char buffer[buffer_size];
int max_socket_descriptor;
int downloaded_files = 1;
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(server_socket, &readfds);
max_socket_descriptor = server_socket;
while(true)
{
if ((select( max_socket_descriptor + 1, &readfds, NULL, NULL, NULL) < 0) && (errno != EINTR))
{
std::cout << "Blad funkcji select." << std::endl;
}
for (int i = 0 ; i < max_clients ; i++)
{
if(FD_ISSET(server_socket, &readfds))
{
int new_sockfd;
if ((new_sockfd = accept(server_socket,(SOCKADDR *)&server, &server_sizeof)) == SOCKET_ERROR)
{
std::cout << "Otrzymanie deskryptora nieudane." << std::endl;
}
else
{
for (int i = 0; i < max_clients; i++)
{
if( client_socket[i] == 0 )
{
client_socket[i] = new_sockfd;
FD_SET( client_socket[i], &readfds);
if(client_socket[i] > max_socket_descriptor)
{
max_socket_descriptor = client_socket[i];
}
std::cout << "Dodawanie do listy socketow jako numer " << i << std::endl;
break;
}
}
}
}
if(FD_ISSET(client_socket[i], &readfds))
{
struct sockaddr_in client_address;
char filename[buffer_size];
std::stringstream ip_filename;
ip_filename << "plik" << downloaded_files << "_" << inet_ntoa(client_address.sin_addr);
strcpy(filename, ip_filename.str().c_str());
std::cout << "Nazwa pliku (IP klienta): " << filename << std::endl;
FILE* file;
memset(buffer, 0, buffer_size);
int received_size;
received_size = recv(client_socket[i], buffer, buffer_size, 0);
if (received_size <= 0)
{
closesocket(client_socket[i]);
FD_CLR(client_socket[i], &readfds);
client_socket[i] = 0;
break;
}
else
{
file = fopen(filename, "ab");
fwrite(buffer, sizeof(char), received_size, file);
fclose(file);
}
downloaded_files++;
}
}
}
closesocket(server_socket);
WSACleanup();
system("pause");
return 0;
}
I thought about opening and closing those files every received packet and appending every packet to them, but I really don't have idea how to do it. The example of modified code was meant to do it, but it doesn't work.
I'm forbidden to use other processes and threads than the main one, so I'm kinda helpless now. Thanks for your help.
You have the basic loop with select in place, which is good.
accept is already (mostly) non-blocking. You just need to turn on non-blocking mode on the client sockets and then you'll be able to handle multiple client reads, writes and accepts in your main select loop.
You can have a vector of client-specific data per client, with each entry containing the client socket, the opened file and any other client-specific state.
After the accept, you create a new client entry and add it to the vector. Then in the main loop you do FD_SET for accept and all client's reads and writes. After the select, you inspect the the FD sets and handle them one by one. For best performance you will want your file I/O also in non-blocking mode, but for this assignment that's probably overkill.

epoll multi process

I continue learn network programming using c/c++, and after that I have created multi process tcp server, I want to create simple http server, which return static resources, I use epoll so let me show my code
first of all I use fd passing for handle request in workers
so, my main function and head process
struct Descriptors{
int sv[2];
};
class Parent{
public:
static Parent& getInstance(){
static Parent instance;
return instance;
}
Parent(Parent const&) = delete;
void operator=(Parent const&) = delete;
void addFd(int fd){
m_fd.push_back(fd);
};
void run() {
startServer();
size_t index = 0;
while(true){
struct epoll_event Events[MAX_EVENTS];
int N = epoll_wait(m_epoll, Events, MAX_EVENTS, -1);
for (size_t i =0; i < N; ++i){
if (Events[i].events & EPOLLHUP){
epoll_ctl(m_epoll, EPOLL_CTL_DEL, Events[i].data.fd, &(Events[i]));
shutdown(Events[i].data.fd,SHUT_RDWR);
close(Events[i].data.fd);
continue;
}else {
if (Events[i].data.fd == m_masterSocket) {
handleConnection();
}else {
char * arg = "1";
ssize_t size = sock_fd_write(m_fd[index], arg, 1,Events[i].data.fd);
index = (1+index) % m_fd.size();
}
}
}
}
}
private:
Parent(){
m_numCpu = sysconf(_SC_NPROCESSORS_ONLN);
}
void startServer(){
m_masterSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in SockAddr;
SockAddr.sin_family = AF_INET;
SockAddr.sin_port = htons(11141);
SockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(m_masterSocket, (struct sockaddr *)(&SockAddr), sizeof(SockAddr));
set_nonblock(m_masterSocket);
listen(m_masterSocket, SOMAXCONN);
m_epoll = epoll_create1(0);
struct epoll_event Event;
Event.data.fd = m_masterSocket;
Event.events = EPOLLIN | EPOLLRDHUP;
epoll_ctl(m_epoll, EPOLL_CTL_ADD, m_masterSocket, &Event);
}
void handleConnection(){
int SlaveSocket = accept(m_masterSocket, 0, 0);
set_nonblock(SlaveSocket);
struct epoll_event Event;
Event.data.fd = SlaveSocket;
Event.events = EPOLLIN | EPOLLRDHUP;
epoll_ctl(m_epoll, EPOLL_CTL_ADD, SlaveSocket, &Event);
}
int m_epoll;
int m_masterSocket;
int m_numCpu;
std::vector<int> m_fd;
};
void parent(int sock){
Parent::getInstance().addFd(sock);
}
int main(int argc, char **argv){
int numCpu = sysconf(_SC_NPROCESSORS_ONLN);
std::vector<Descriptors> desc;
desc.resize(numCpu);
bool isParent = true;
for (int i = 0; i < numCpu && isParent; ++i){
std::cout << "pid my is = " << getpid() <<std::endl;
int sv[2];
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) < 0) {
perror("socketpair");
exit(1);
}
pid_t forkId = fork();
switch (forkId){
case 0:{
isParent = false;
close(sv[0]);
child(sv[1]);
break;
}
case -1:
perror("fork");
exit(1);
default:
close(sv[1]);
parent(sv[0]);
break;
}
}
if (isParent){
Parent::getInstance().run();
int status;
waitpid(-1, &status, 0);
}
}
And my worker process is
void respond(int fd)
{
char mesg[99999], *reqline[3], data_to_send[BYTES], path[99999];
int rcvd, fileDesc, bytes_read;
memset( (void*)mesg, (int)'\0', 99999 );
const char *ROOT = "/home/web_server/";
int RecvResult = recv(fd,mesg, 99999, MSG_NOSIGNAL);
if (RecvResult == 0 && errno != EAGAIN){
shutdown(fd,SHUT_RDWR);
close(fd);
}else if (RecvResult >0){
printf("%s", mesg);
reqline[0] = strtok (mesg, " \t\n"); // split on lexemes
if ( strncmp(reqline[0], "GET\0", 4)==0 ) // if first 4 character equal
{
reqline[1] = strtok (NULL, " \t");
reqline[2] = strtok (NULL, " \t\n");
std::cout << "reqline 1 " << reqline[1] << std::endl;
std::cout << "reqline 2 " << reqline[2] << std::endl;
if ( strncmp( reqline[2], "HTTP/1.0", 8)!=0
&& strncmp(reqline[2], "HTTP/1.1", 8 ) !=0 )
{
write(fd, "HTTP/1.0 400 Bad Request\n", 25);
}
else
{
if ( strncmp(reqline[1], "/\0", 2)==0 )
reqline[1] = "/index.html";
strcpy(path, ROOT);
strcpy(&path[strlen(ROOT)], reqline[1]);
printf("file: %s\n", path);
if ( (fileDesc=open(path, O_RDONLY))!=-1 )
{
send(fd, "HTTP/1.0 200 OK\n\n", 17, 0);
while ( (bytes_read=read(fileDesc, data_to_send, BYTES))>0 )
write (fd, data_to_send, bytes_read);
}
else write(fd, "HTTP/1.0 404 Not Found\n", 23);
}
}
}
shutdown(fd,SHUT_RDWR);
close(fd);
}
void child(int sock)
{
int fd;
char buf[16];
ssize_t size;
sleep(1);
for (;;) {
size = sock_fd_read(sock, buf, sizeof(buf), &fd);
if (size <= 0)
break;
if (fd != -1) {
respond(fd);
}
}
printf("child processes is end\n");
}
And when I go in browser http://127.0.0.1:11141/ it is ok, and I get index.html, but when I run in apache benchmark, as
ab -n 10 -c 10 http://127.0.0.1:11141/
I get answer as
This is ApacheBench, Version 2.3
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 127.0.0.1 (be patient)...apr_socket_recv: Connection reset by peer (104)
Total of 2 requests completed
I don't understand where is my error, because I I think that my server in theory(because using epoll ) have to resolved C10K problem. but on the practice, my server can not resolved 10 connection. Could you help me please?
Thank you for useful links and any advices!
UPDATE
When I run as
strace -f ./server 2> error.txt
in end of error.txt
[pid 6552] write(6, 0x7ffdbff00390, 757) = -1 EPIPE (Broken pipe)
[pid 6552] --- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=6552, si_uid=1000} ---
[pid 6552] +++ killed by SIGPIPE +++
write(1, 0x7fc5ffbe3000, 83) = 83
write(1, 0x7fc5ffbe3000, 12) = 12
write(1, 0x7fc5ffbe3000, 20) = 20
write(1, 0x7fc5ffbe3000, 41) = 41
open(0x7ffdbff18e30, O_RDONLY) = 11
sendto(10, 0x403df9, 17, 0, NULL, 0) = 17
read(11, 0x7ffdbff00390, 1024) = 757
write(10, 0x7ffdbff00390, 757) = -1 EPIPE (Broken pipe)
--- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=6554, si_uid=1000} ---
+++ killed by SIGPIPE +++
So I think that problem in EPipe error, But I don't understand why...
Update
So I think that problem in close descriptor, but I don't understand how to fix it. Thank you for useful advices.
UPDATE
I Get error on function send in worker process
Seems I found my error, right version function void :
void respond(int fd)
{
char mesg[99999], *reqline[3], data_to_send[BYTES], path[99999];
int rcvd, fileDesc, bytes_read;
memset( (void*)mesg, (int)'\0', 99999 );
const char *ROOT = "/home/web_server/";
int RecvResult = recv(fd,mesg, 99999, MSG_NOSIGNAL);
//EAGAIN - "there is no data available right now, try again later
if (RecvResult == 0 && errno != EAGAIN){
shutdown(fd,SHUT_RDWR);
close(fd);
std::cout << "error recv" << std::endl;
return;
}else if (RecvResult >0){
printf("%s", mesg);
reqline[0] = strtok (mesg, " \t\n"); // split on lexemes
if ( strncmp(reqline[0], "GET\0", 4)==0 ) // if first 4 character equal
{
reqline[1] = strtok (NULL, " \t");
reqline[2] = strtok (NULL, " \t\n");
std::cout << "reqline 1 " << reqline[1] << std::endl;
std::cout << "reqline 2 " << reqline[2] << std::endl;
if ( strncmp( reqline[2], "HTTP/1.0", 8)!=0
&& strncmp(reqline[2], "HTTP/1.1", 8 ) !=0 )
{
send(fd, "HTTP/1.0 400 Bad Request\n", 25 , MSG_NOSIGNAL);
}
else
{
if ( strncmp(reqline[1], "/\0", 2)==0 )
reqline[1] = "/index.html";
strcpy(path, ROOT);
strcpy(&path[strlen(ROOT)], reqline[1]);
printf("file: %s\n", path);
if ( (fileDesc=open(path, O_RDONLY))!=-1 )
{
send(fd, "HTTP/1.0 200 OK\n\n", 17, MSG_NOSIGNAL);
while ( (bytes_read=read(fileDesc, data_to_send, BYTES))>0 )
{
if (bytes_read != -1)
send (fd, data_to_send, bytes_read, MSG_NOSIGNAL);
}
}
else send(fd, "HTTP/1.0 404 Not Found\n", 23, MSG_NOSIGNAL);
}
shutdown(fd,SHUT_RDWR);
close(fd);
}
}else {
std::cout << "Client disconnected unexpect" << std::endl;
}
}
Problem was that , that I close socket , and after that I try to read from this socket.

winsock recv returning 0 without shutdown from peer, different behavior from when compiling for console

I'm having an issue with winsock on windows 8.1 where recv keeps returning 0 randomly. I'm running both client and server on the same machine (thus all traffic is pointed at the loopback address) and i have breakpoints on any statement on both client and server which would shut down the sockets. But when the issue occurs the server is still operating normally, and hasn't shutdown anything, while the client has hit a breakpoint that only triggers on recv returning 0 or less.
The client keeps returning 0 from recv randomly (although always at the same point in my code) when the server VS 2013 project is set to compile as a windows program (rather than a console, in order to make it produce no window, it's supposed to be silent running). The bug doesn't seem to occur when i compile the server as a console application, as I've been debugging the program in that mode and only come across this issue when i switched compilation settings.
Is there any way to launch a console window when compiling as a windows application so i can see any debug statements?
Does winsock behave differently when compiling for the console vs compiling for a windows application?
Why would the client's recv return 0, when I've not sent a shutdown signal from the server?
My code, ask if there's any more you need:
Client
void recvLoop()
{
int recievedBytes = 1;
while (running && recievedBytes > 0)
{
WORD dataSize;
WORD dataType;
int recievedBytesA = ConnectSock.Recieve(&dataSize, sizeof(WORD));
if (recievedBytesA <= 0)
{
closing = true; //breakpoint set here
attemptKillThreads();
continue;
}
int recievedBytesB = ConnectSock.Recieve(&dataType, sizeof(WORD));
if (recievedBytesB <= 0)
{
closing = true; //breakpoint set here
attemptKillThreads();
continue;
}
unique_ptr<char[]> data(new char[dataSize]);
int recievedBytesC = ConnectSock.Recieve(data.get(), dataSize);
if (recievedBytesC <= 0)
{
closing = true; //breakpoint set here - Always triggers here
attemptKillThreads();
continue;
}
//use the received data.....
}
}
When this breaks recievedBytesA = 2, recievedBytesB = 2, recievedBytesC = 0, dataType = 0, dataSize = 0
ConnectSock is a global of type ConnectSocket. here is its Recieve()
int ConnectSocket::Recieve(void *recvbuf, int recvbuflen)
{
if (sock != INVALID_SOCKET)
{
int i = recv(sock, (char *)recvbuf, recvbuflen, 0);
if ((i == SOCKET_ERROR))
{
int err = 0;
err = WSAGetLastError();
if (err != WSAEINTR)
{
//ignore WSAEINTR as that's likely to be because of a shutdown complating a bit awkwardly
cout << "error: " << err << endl;
}
}
return i;
}
return -2;
}
Server:
void sendLoop()
{
int bytessent = 0;
QueuePack tosend;
while (running)
{
tosend = sendQueue.Dequeue();
if (tosend.packType == QueuePack::EXIT || tosend.packType == 0 || tosend.dSize == 0)
{
attemptKillThreads();
continue;
}
bytessent = Connection->SendData(&tosend.dSize, sizeof(WORD));
//cout used to see what exactly is being sent, even if it is garbage when converted to text
cout << tosend.dSize << endl;
cout << bytessent << endl;
if (bytessent <= 0)
{
attemptKillThreads();
continue;
}
bytessent = Connection->SendData(&tosend.packType, sizeof(WORD));
cout << tosend.dSize << endl;
cout << bytessent << endl;
if (bytessent <= 0)
{
attemptKillThreads();
continue;
}
bytessent = Connection->SendData(tosend.bufferPtr(), tosend.dSize);
cout << tosend.bufferPtr() << endl;
cout << bytessent << endl;
if (bytessent <= 0)
{
attemptKillThreads();
}
}
if (Connection->shutdownSock(SD_SEND) == SOCKET_ERROR)
{
Connection->closeSock();
}
}
SendData is literally a wrapper for send that uses a reinterpret_cast
int SendData(void * writeBuffer, int bufferSize)
{
return send(SocketManager.clientSocket, reinterpret_cast<char *>(writeBuffer), bufferSize, 0);
}
sendQueue is a Bounded blocking queue that holds QueuePacks
QueuePacks are used to transfer data, it's size and what kind of data it is between threads. both Client and server use this as it allows me to make sure data gets to the right thread on the client
Queuepack has 2 public variables packType and dSize of type WORD.
QueuePack::QueuePack() : packType(UND), dSize(0)
{
int h = 0; //debug statement to break on - never gets hit after initial collection construction occurs
}
QueuePack::QueuePack(const WORD type, WORD size, char * data) : packType(type), dSize(size)
{
//debug test and statement to break on
if (size == 0 || type == 0)
{
int h = 0; //breakpoint - never gets hit
}
dSize = (dSize < 1 ? 1 : dSize);
_buffer = make_unique<char[]>(dSize);
memcpy(_buffer.get(), data, dSize);
}
QueuePack::QueuePack(QueuePack &other) : packType(other.packType), dSize(other.dSize)
{
//debug test and statement to break on
if (other.dSize == 0 || other.packType == 0)
{
int h = 0; //breakpoint - never gets hit
}
if (&other == this)
{
return;
}
_buffer = make_unique<char[]>(dSize);
other.buffer(_buffer.get());
}
QueuePack QueuePack::operator= (QueuePack &other)
{
// check for self-assignment
if (&other == this)
{
return *this;
}
// reuse storage when possible
if (dSize != other.dSize)
{
_buffer.reset(new char[other.dSize]);
dSize = other.dSize;
}
packType = other.packType;
other.buffer(_buffer.get());
return *this;
}
QueuePack::~QueuePack()
{
}
HRESULT QueuePack::buffer(void* container)
{
try
{
memcpy(container, _buffer.get(), dSize);
}
catch (...)
{
return E_FAIL;
}
return S_OK;
}
char * QueuePack::bufferPtr()
{
return _buffer.get();
}
When this breaks recievedBytesA = 2, recievedBytesB = 2, recievedBytesC = 0, dataType = 0, dataSize = 0
You are calling ConnectSock.Recieve() when dataSize is 0. There is nothing to read, so Receive() reports that 0 bytes were read.
You need to add a check for that condition:
unique_ptr<char[]> data(new char[dataSize]);
if (dataSize != 0) // <-- add this
{
int recievedBytesC = ConnectSock.Recieve(data.get(), dataSize);
if (recievedBytesC <= 0)
{
closing = true;
attemptKillThreads();
continue;
}
}
Your code is also assuming that Recieve() reads all bytes that are requested, it is not handling the possibility that recv() may return fewer bytes. So you need to make Recieve() call recv() in a loop to guarantee that everything requested is actually read:
int ConnectSocket::Recieve(void *recvbuf, int recvbuflen)
{
if (sock == INVALID_SOCKET)
return -2;
char *buf = static_cast<char *>(recvbuf);
int total = 0;
while (recvbuflen > 0)
{
int i = recv(sock, buf, recvbuflen, 0);
if (i == SOCKET_ERROR)
{
int err = WSAGetLastError();
if (err != WSAEINTR)
{
//ignore WSAEINTR as that's likely to be because of a shutdown complating a bit awkwardly
cout << "error: " << err << endl;
}
return -1;
}
if (i == 0)
{
cout << "disconnected" << endl;
return 0;
}
buf += i;
recvbuflen -= i;
total += i;
}
return total;
}
Same with SendData(), as send() may return fewer bytes than requested:
int SendData(void * writeBuffer, int bufferSize)
{
if (SocketManager.clientSocket == INVALID_SOCKET)
return -2;
char *buf = static_cast<char *>(writeBuffer);
int total = 0;
while (bufferSize > 0)
{
int i = send(SocketManager.clientSocket, buf, bufferSize, 0);
if (i == SOCKET_ERROR)
{
int err = WSAGetLastError();
if (err != WSAEINTR)
{
//ignore WSAEINTR as that's likely to be because of a shutdown complating a bit awkwardly
cout << "error: " << err << endl;
}
return -1;
}
buf += i;
bufferSize -= i;
total += i;
}
return total;
}

Creating daemon file which listen continous without any external execution

I have deamon process. Which works as server socket. And to make it listening I execute it in terminal manually : ./daemon
Now When I want to keep this on ftp server, ther I could not execute in that manner. So I want it to keep listening by deafult.
I see on goolge for how to creat it. It says that child and parent process with two fork() will work as daemon process. But I could not figure out which process ID should used where. Here is my code, Can some one please guide:
using namespace std;
void *SocketHandler(void *);
int main(int argv, char **argc)
{
int host_port = 1103;
char buf[20];
int k;
struct sockaddr_in my_addr;
int hsock;
int *p_int;
int err;
socklen_t addr_size = 0;
int *csock;
sockaddr_in sadr;
pthread_t thread_id = 0;
hsock = socket(AF_INET, SOCK_STREAM, 0);
if (hsock == -1) {
printf("Error initializing socket %dn", errno);
goto FINISH;
}
p_int = (int *) malloc(sizeof(int));
*p_int = 1;
if ((setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char *) p_int, sizeof(int)) == -1) || (setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char *) p_int, sizeof(int)) == -1)) {
printf("Error setting options %dn", errno);
free(p_int);
goto FINISH;
}
free(p_int);
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(host_port);
memset(&(my_addr.sin_zero), 0, 8);
my_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(hsock, (sockaddr *) & my_addr, sizeof(my_addr)) == -1) {
fprintf(stderr, "Error binding to socket, make sure nothing else is listening on this port %dn", errno);
goto FINISH;
}
if (listen(hsock, 10) == -1) {
fprintf(stderr, "Error listening %dn", errno);
goto FINISH;
}
//Now lets do the server stuff
addr_size = sizeof(sockaddr_in);
while (true) {
printf("waiting for a connectionn\n");
csock = (int *) malloc(sizeof(int));
if ((*csock = accept(hsock, (sockaddr *) & sadr, &addr_size)) != -1) {
printf("---------------------nReceived connection from %s\n", inet_ntoa(sadr.sin_addr));
pthread_create(&thread_id, 0, &SocketHandler, (void *) csock);
pthread_detach(thread_id);
} else {
fprintf(stderr, "Error accepting %dn", errno);
}
}
FINISH:
;
}
std::pair < int, std::string > mytransform(const std::pair < std::string, int >p)
{
return std::pair < int, std::string > (p.second, p.first);
}
void *SocketHandler(void *lp)
{
int ar[10];
int result=0;
int *csock = (int *) lp;
char buf[20];
int k;
char *skp;
char *str;
char *str2;
std::stringstream ss;
std::multimap < int, std::string, std::greater < int >>dst;
std::multimap < int, std::string >::iterator rec;
std::map < std::string, int >src;
std::map < int, std::vector < std::string > >three_highest;
std::vector < std::string > writable;
std::string item;
std::ostringstream bfr;
std::string result_string;
std::istringstream iss;
std::ostringstream oss;
// std::multimap < int, std::string >::iterator it;
std::vector<std::string> most;
int max_count = 0;
int tmp=0;
int pcount = 0, ncount = 0;
char buffer[1024];
int buffer_len = 1024;
int bytecount;
int i = 0,t=0,q=0;
int j = 0;
char *ch[50] = { 0 }; /* stores references to 50 words. */
char *ch2[50] = { 0 };
char *excluded_string[50] = { 0 };
char *word = strtok(buffer, " ");
char *word2 = strtok(buffer, " ");
char *portstring1=(char *)malloc(sizeof(buffer));
char *portstring2=(char *)malloc(sizeof(buffer));
memset(buffer, 0, buffer_len);
if ((bytecount = recv(*csock, buffer, buffer_len, 0)) == -1) {
fprintf(stderr, "Error receiving data %d \n", errno);
goto FINISH;
}
printf("Received bytes %d \nReceived string %s \n ", bytecount, buffer);
word = strtok(buffer, " ");
while ((NULL != word) && (50 > i)) {
ch[i] = strdup(word);
excluded_string[j]=strdup(word);
word = strtok(NULL, " ");
skp = BoyerMoore_skip(ch[i], strlen(ch[i]) );
if(skp != NULL)
{
i++;
continue;
}
printf("exclueded : %s and %s size %d \n",excluded_string[j],ch[i],sizeof(excluded_string));
bfr << excluded_string[j] << " ";
result_string = bfr.str();
j++;
// std::cout << "string is :" << r1;
}
std::cout << "string is :" << result_string << "\n";
ss<<result_string;
while (std::getline(ss, item, ' ')) {
writable.push_back(item);
}
for (std::vector < std::string >::iterator it = writable.begin(); it != writable.end(); it++)
++src[*it];
std::transform(src.begin(), src.end(), std::inserter(dst, dst.begin()), mytransform);
rec=dst.begin();
for (auto it = dst.begin(); it != dst.end(); ++it)
std::cout << it->second << ":" << it->first << std::endl;
while (three_highest.size() < 3 && rec != dst.end()) {
three_highest[rec->first].push_back(rec->second);
rec++;
}
//std::cout << "\nthree_highest:\n";
i=0;
for (std::map < int, std::vector < std::string > >::iterator hit = three_highest.begin(); hit != three_highest.end(); ++hit) {
//std::cout << hit->first << ":";
for (std::vector < std::string >::iterator vit = (*hit).second.begin(); vit != (*hit).second.end(); vit++) {
std::cout << hit->first << ":";
std::cout << *vit << "\n";
ar[i]= hit-> first;
printf(" ar : %d \n",ar[i]);
i++;
oss << hit->first << " " << *vit << "\n";
}
}
printf( "i is :%d \n",i);
if ((bytecount = send(*csock, (char *)ar, i *sizeof(int), 0)) == -1) { // Here we cant send lenth-1. It consider exact
fprintf(stderr, "Error sending data %d\n", errno);
goto FINISH;
}
FINISH:
free(csock);
return 0;
}
You should start with a simpler problem. It seems that in this case you have issues with creating a daemon. This is a good tutorial that was very useful for me when I was learning.