Sending data to multiple clients connected on my Server - c

I have this server app where clients can connect to. Now i want that when the clients are connected i can send data to all of them. I manage to do it when i connect my two clients.. what i send is received by my two clients. but my problem is when i connect client1 then send data to server, client1 can receive data then i connect client2 and i send data to the server. now when i send data from server to my clients only client1 can receive data but when i disconnect client 1 then client2 can receive data from the server.
How can i make them work at the same time?.. Also how can i make my server accept messages at the same time from my client?..
Here's the part of the code im having trouble.
for(j=0;j<MAX_CLIENTS; j++)
Clients[j].connected_sock = -1;
do
{
fduse = fdin;
printf("Waiting for Connection\n");
err = select(sMax + 1, &fduse, NULL, NULL, NULL);
if (err < 0)
{
perror(" select() failed");
break;
}
DescRead = err;
for (SockStorage=0; SockStorage <= sMax && DescRead > 0; ++SockStorage)
{
if (FD_ISSET(SockStorage, &fduse))
{
DescRead -= 1;
if (SockStorage == socketFd)
{
printf(" Listening socket is readable\n");
do
{
NewSFD = accept(socketFd,(struct sockaddr *) &cli_addr, &clilen);
if (NewSFD < 0)
{
if (errno != EWOULDBLOCK)
{
perror(" accept() failed");
DCSERVER = TRUE;
}
break;
}
if(ClientCount < MAX_CLIENTS){
for(loop = 0; loop <MAX_CLIENTS; loop++){
if(Clients[loop].connected_sock<0){
Clients[loop].connected_sock = NewSFD;
break;
}
}
ClientCount++;
}
else
{
printf("Maximum Client Reached.\n");
char *sendtoclient = "Server full. ";
send(NewSFD, sendtoclient, strlen(sendtoclient),0);
close(NewSFD);
break;
}
ip = ntohl(cli_addr.sin_addr.s_addr);
printf(" Connection from %d.%d.%d.%d\n",
(int)(ip>>24)&0xff,
(int)(ip>>16)&0xff,
(int)(ip>>8)&0xff,
(int)(ip>>0)&0xff);
dlogs(ip);
FD_SET(NewSFD, &fdin);
if (NewSFD > sMax)
sMax = NewSFD;
} while (NewSFD != -1);
}
else
{
int d;
for(d=0; d<MAX_CLIENTS; d++){
printf("Descriptor ID: %d\n", Clients[d].connected_sock);
}
pfds[0].fd = fd;
pfds[0].events = POLLIN;
pfds[1].fd = SockStorage;
pfds[1].events = POLLIN;
state = FALSE;
do
{
rc = poll(pfds, 2, -1);
if (pfds[0].revents & POLLIN)
{
while ((nbytes = read(fd, buf, sizeof(buf)-1)) > 0)
{
buf[nbytes] = '\0';
printf("%s\n", buf);
}
pfds[0].events = 0;
pfds[1].events = POLLIN | POLLOUT;
}
if (pfds[1].revents & POLLIN)
{
err = recv(SockStorage, strbuf, sizeof(strbuf), 0);
if (err < 0)
{
if (errno != EWOULDBLOCK)
{
perror(" recv() failed");
state = TRUE;
}
break;
}
if (err == 0)
{
printf(" Connection closed\n");
state = TRUE;
break;
}
dSize = err;
printf(" %d bytes received\n", dSize);
}
if (pfds[1].revents & POLLOUT)
{
int s;
for(s=0; s<MAX_CLIENTS; s++){
if(Clients[s].connected_sock>0){
err = send(Clients[s].connected_sock, buf, strlen(buf), 0);
if (err < 0)
{
perror(" send() failed");
state = TRUE;
break;
}
}
}
pfds[0].events = POLLIN;
pfds[1].events = POLLIN;
}
} while (TRUE);
Here's how im sending data to my clients.
int s;
for(s=0; s<MAX_CLIENTS; s++){
if(Clients[s].connected_sock>0){
err = send(Clients[s].connected_sock, buf, strlen(buf), 0);
if (err < 0)
{
perror(" send() failed");
state = TRUE;
break;
}
}
}
Thanks,

There are generally couple of possible solutions:
You can use separate threads for each client connection;
You can use select;
You can use poll;
You can use epoll;
In Windows environment there are also some other possibilities like IOCP for example.
Each of mentioned solutions have some pros and cons (you need generally distinguish between simplicity and performance).
You can read some network programming tutorial for more details, e.g. this.

Related

SSL_connect from a client while the server is in SSL_read

I have a non-blocking socket and using select to handle connections from multiple SSL clients :
I have tried suggestions regarding handling SSL_ERROR_WANT_READ, like repeat SSL_read call, or return back to Select, but it seems to be not working in my case.
while (1)
{
start:
if (readyCount = select(FD_SETSIZE, &read_fd_set, NULL, NULL, &timeout) < 0)
{
exit(EXIT_FAILURE);
}
for (int i = 0; i < FD_SETSIZE; ++i)
if (FD_ISSET(i, &read_fd_set))
{
if (i == sockfd)
{
newSocket = accept(sockfd, (struct sockaddr *) &clientname, (socklen_t*)&size);
}
else
{
ssl = SSL_new(ctx);
SSL_set_fd(ssl, i);
accept:
int err = SSL_accept(ssl);
if (0 >= err)
{ // it never goes here
int resultCode = SSL_get_error(ssl, err);
switch (resultCode)
{
case SSL_ERROR_NONE:
goto accept;
break;
case SSL_ERROR_ZERO_RETURN:
SSL_shutdown(ssl);
break;
case SSL_ERROR_SYSCALL:
break;
case SSL_ERROR_WANT_READ:
break;
case SSL_ERROR_WANT_WRITE:
break;
case SSL_ERROR_WANT_CONNECT:
break;
case SSL_ERROR_WANT_ACCEPT:
goto accept;
break;
case SSL_ERROR_WANT_X509_LOOKUP:
break;
case SSL_ERROR_SSL:
break; }
default:
break;
}
}
else
{
Call_Read(...)
}
SSL_free(ssl);
close(i);
FD_CLR(i, &active_fd_set);
}
}
}
Call_Read(...)
{
int fd = SSL_get_fd(ssl);
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
while (data_size > 0)
{
bytes_recv = SSL_read(ssl, data, data_size);
if (bytes_recv <= 0)
{
if (SSL_ERROR_WANT_READ == SSL_get_error(ssl, bytes_recv))
{
testtt = SSL_pending(ssl); //always 0
/*SSL_renegotiate(ssl);
SSL_do_handshake(ssl);*/
continue;
}
if (SSL_ERROR_WANT_WRITE == SSL_get_error(ssl, bytes_recv))
{
testtt = SSL_pending(ssl);
int blocked_on_SSL_ERROR_WANT_WRITE = 1;
continue; }
}
return bytes_recv;
}
data += bytes_recv;
data_size -= bytes_recv;
}
return 1;
}
Client Write:
{
while (data_size > 0)
{
bytes_sent = SSL_write(ssl, data_ptr, data_size);
if (errno == EPIPE) == doesn’t reach this line, debugger stops with EPIPE
{
printf("WRITE socket returned EPIPE”);
return -1;
}
if (bytes_sent < 0)
{
int err = SSL_get_error(ssl, bytes_sent);
switch (err)
{
case SSL_ERROR_WANT_READ:
printf(" SSL_ERROR_WANT_READ\n");
case SSL_ERROR_WANT_WRITE:
printf(" SSL_ERROR_WANT_WRITE\n");
default:
;
}
}
data_ptr += bytes_sent;
data_size -= bytes_sent;
}
return 1;
}
I don’t know how to handle the situation, when the server is in SSL_Read and some of clients calls SSL_Connect.
In such a scenario, the Call_Read will be in infinite loop for SSL_ERROR_WANT_READ. If I replace the “continue” statement with a flag that will finish the loop and the caller returns back to Select the client will break with broken pipe error, and it even doesn’t reach the line “WRITE socket returned EPIPE”. The same will happen if I return from the read loop back to Accept, instead of to Select.
I am missing here something and I am wondering if I should do some changes to the client also.
Any suggestions?

Client-server echo-chat (multiplexing I/O + threads)

I just started learning C language and I'm trying to get deal with Windows Sockets.
The problem is the server can accept and send message only once.
I used debug mode and saw that work stops in select() from the server part. It seems fine in client (but I'm not sure) and don't see the problem in my code. But I have such a result. What's wrong?
I noticed that my tv.tv_sec isn't defined and I did that just before select, nothing was changed.
And just to be sure: as I need to receive and send message, I don't need write descriptor in accept(), right?
Client uses CreateThread function where I try to send message. Send is in while(1) cycle in main()
Server part:
int main(int argc, char* argv[])
{
/* definitions, WSAStartup(), socket(), bind(), listen()
Listening socket is a returned value of listen() function*/
FD_ZERO(&readSet);
FD_ZERO(&writeSet);
while (1)
{
// SELECT (LISTENING SOCKET)
FD_ZERO(&readSet);
FD_SET(listeningSocket, &readSet);
tv.tv_sec = 5;
printf("Listening: Read FD: %d; Write FD : %d;\n", FD_ISSET(listeningSocket, &readSet), FD_ISSET(listeningSocket, &writeSet));
if ((retVal = select(listeningSocket + 1, &readSet, NULL, NULL, 0)) == SOCKET_ERROR)
{
printf("Select error ");
break;
}
else if (retVal == 0)
{
printf(". . .\n");
continue;
}
else
{
// READ SD
if ((FD_ISSET(listeningSocket, &readSet)) != SOCKET_ERROR)
{
if ((newSocketDescriptor = accept(listeningSocket, (struct sockaddr *)&clientAddr, &clientAddrSize)) == SOCKET_ERROR)
{
printf("Accept error ");
break;
}
FD_ZERO(&readSet);
FD_SET(newSocketDescriptor, &readSet);
HOSTENT *hst = gethostbyaddr((const char *)&serverAddr.sin_addr.s_addr, 4, AF_INET);
printf("Welcome %s (%s:%d) new connected\n", hst->h_name, inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));
printf("Read FD: %d; Write FD : %d;\n", FD_ISSET(newSocketDescriptor, &readSet), FD_ISSET(newSocketDescriptor, &writeSet));
// READ
if (FD_ISSET(newSocketDescriptor, &readSet) != 0)
{
if ((numBytes = recv(newSocketDescriptor, &bufferData[0], sizeof(bufferData), 0)) == SOCKET_ERROR)
{
printf("Recv failed \n");
freeSocketInformation(newSocketDescriptor);
break;
}
bufferData[numBytes] = '\0';
printf("Client -> Server: %s\n", &bufferData[0]);
}
// WRITE
FD_ZERO(&writeSet);
FD_SET(newSocketDescriptor, &writeSet);
printf("Read FD: %d; Write FD : %d;\n", FD_ISSET(newSocketDescriptor, &readSet), FD_ISSET(newSocketDescriptor, &writeSet));
if (FD_ISSET(newSocketDescriptor, &writeSet) != 0)
{
//fgets(&bufferData[0], sizeof(bufferData), stdin);
if (send(newSocketDescriptor, &bufferData[0], strlen(&bufferData[0]), 0) == SOCKET_ERROR)
{
printf("Send error ");
freeSocketInformation(newSocketDescriptor);
break;
}
bufferData[numBytes] = '\0';
printf("Server -> Client: %s\n", &bufferData[0]);
}
printf("Read FD: %d; Write FD : %d;\n", FD_ISSET(newSocketDescriptor, &readSet), FD_ISSET(newSocketDescriptor, &writeSet));
FD_SET(newSocketDescriptor, &readSet);
}
}
}
//FD_CLR(listeningSocket, &readSet);
closesocket(newSocketDescriptor);
} while (FALSE);
printf("- Error code: %d\n", WSAGetLastError());
closesocket(listeningSocket);
WSACleanup();
return 0;
}
Client part (it uses CreateThread function which is in the end of the code):
/* definitions, socket(), connect()*/
if (ioctlsocket(socketDescriptor, FIONBIO, (unsigned long *)&nb) != 0)
{
printf("ioctlsocket error ");
break;
}
FD_ZERO(&writeSet);
FD_SET(socketDescriptor, &writeSet);
if ((retVal = select(socketDescriptor + 1, NULL, &writeSet, NULL, &tv)) == SOCKET_ERROR)
{
printf("Send non-blocking error ");
break;
}
else if (retVal == 0)
{
printf("Non-blocking connect time limit is expired");
break;
}
}
printf("Connection with %s\n", SERVERADDR);
DWORD thID;
printf("Socket Desciptor: %d\n", socketDescriptor);
HANDLE hThread = CreateThread(NULL, NULL, HandleReadThread, (LPVOID)socketDescriptor, NULL, &thID);
printf("Thread ID: %d\n", thID);
while (1)
{
// WRITE
printf("Client -> Server: ");
fgets(&bufferData[0], sizeof(bufferData), stdin);
FD_ZERO(&writeSet);
FD_SET(socketDescriptor, &writeSet);
tv.tv_sec = 5;
if ((retVal = select(socketDescriptor + 1, NULL, &writeSet, NULL, &tv)) == SOCKET_ERROR)
{
printf("Send non-blocking error ");
break;
}
if (FD_ISSET(socketDescriptor, &writeSet) != 0)
{
if (send(socketDescriptor, bufferData, strlen(&bufferData[0]), 0) == SOCKET_ERROR)
{
printf("Send error ");
break;
}
}
}
} while (FALSE);
printf("- Error code: %d\n", WSAGetLastError());
closesocket(socketDescriptor);
WSACleanup();
return 0;
}
DWORD WINAPI HandleReadThread(LPVOID serverSocket)
{
SOCKET socketDescriptor;
socketDescriptor = (SOCKET)serverSocket;
char bufferData[MAXDATASIZE] = { 0 };
int retVal;
fd_set readSet;
timeval tv = { 0 };
tv.tv_sec = 5;
int numBytes;
int nclients = 0;
while (1)
{
FD_ZERO(&readSet);
FD_SET(socketDescriptor, &readSet);
if ((retVal = select(socketDescriptor + 1, &readSet, NULL, NULL, &tv)) == SOCKET_ERROR)
{
printf("Select error. Error code: %d", WSAGetLastError());
break;
}
else if (retVal == 0)
{
//printf(". . .\n");
continue;
}
else
{
//FD_ZERO(socketDescriptor, &readSet);
//FD_SET(socketDescriptor, &readSet);
// READ
if (FD_ISSET(socketDescriptor, &readSet) != 0)
{
if ((numBytes = recv(socketDescriptor, &bufferData[0], sizeof(bufferData), 0)) == SOCKET_ERROR)
{
printf("Recv error in Thread. Error code: %d\n", WSAGetLastError());
break;
}
printf("\nSocket Desciptor: %d\n", socketDescriptor);
bufferData[numBytes] = '\0';
printf("Server -> Client: %s\n", &bufferData[0]);
}
}
}
closesocket(socketDescriptor);
return 0;
}
Well, I solved it by myself. The condition
if ((FD_ISSET(listeningSocket, &readSet)) != 0)
worked for all while(1) cycle, it should has been finished after accept() function.
Also I added these lines in the beginning of while(1) after FD_SET for readSet:
if (newSocketDescriptor)
{
FD_SET(newSocketDescriptor, &readSet);
}
The chat started working but there are a lot of stuffs to work at :)

Create HTTP GET in C return 301 redirect using IP address

I want to send a GET request to a page and retrieve it to use later to a crawler
I have implemented my own D.N.S. resolver (like DIG command in LINUX) and I want to use the ip address to get the http page
I have the following code
typedef struct http_request
{
request_type req_type;
char* ip;
int port_number;
char* path;
char* data;
char* hostname;
}http_request;
typedef struct http_response
{
char* raw_response;
int status_code;
char* status_text;
char* body;
char* server_name;
int content_length;
char* content_type;
}http_response;
// main method
http_response* send_http_request(http_request* request) {
if (request == NULL) {
printf("HTTP request is NULL.\n");
return NULL;
}
http_response* response = (http_response*) malloc(sizeof(http_response));
if (response == NULL) {
exit(1);
return NULL;
}
char http_request_buffer[REQUEST_BUFF_SIZE];
memset(http_request_buffer, 0, REQUEST_BUFF_SIZE);
sprintf(http_request_buffer, "GET /%s HTTP/1.1\r\nHost:%s\r\n\r\n",
request->path, request->ip);
process_http_request(request, http_request_buffer, response);
return response;
}
static int process_http_request(http_request* request,
char* http_request_buffer, http_response* response) {
int socketfd;
struct sockaddr_in socket_details;
char temp_buffer[TEMP_BUFF_SIZE];
char* http_response_buffer;
ssize_t bytes_sent = 0;
ssize_t total_bytes_sent = 0;
ssize_t bytes_received = 0;
ssize_t total_bytes_received = 0;
int status;
http_response_buffer = (char*) malloc(RESPONSE_BUFF_SIZE);
if (http_response_buffer == NULL) {
printf(
"process_http_request: memory allocation failed for response buffer.\n");
return HTTP_ERROR_MEM_ALLOC_FAILED;
}
memset(http_response_buffer, 0, RESPONSE_BUFF_SIZE);
socketfd = socket(AF_INET, SOCK_STREAM, 0);
if (socketfd == -1) {
printf("process_http_request: socket creation failed.\n");
return HTTP_ERROR_SOCKET_CREATION_FAILED;
}
struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
if (setsockopt(socketfd, SOL_SOCKET, SO_RCVTIMEO, (char *) &timeout,
sizeof(timeout)) < 0)
printf("process_http_request: socket option setting failed.\n");
bzero(&socket_details, sizeof(socket_details));
socket_details.sin_family = AF_INET;
socket_details.sin_addr.s_addr = inet_addr(request->ip);
socket_details.sin_port = htons(request->port_number);
if (connect(socketfd, (struct sockaddr*) &socket_details,
sizeof(struct sockaddr)) == -1) {
printf("process_http_request: Could not connect to the server.\n");
return HTTP_ERROR_SERVER_CONN_FAILED;
}
while (1) {
bytes_sent = send(socketfd, http_request_buffer,
strlen(http_request_buffer), 0);
if (bytes_sent < 0) {
printf("process_http_request: error writing on socket\n");
close(socketfd);
return HTTP_ERROR_SOCKET_WRITE_FAILED;
} else {
printf(
"process_http_request: wrote %d bytes data on socket successfully.\n",
(int) bytes_sent);
}
total_bytes_sent += (int) bytes_sent;
printf("process_http_request: total bytes sent = %d\n",
(int) total_bytes_sent);
if (total_bytes_sent == strlen(http_request_buffer))
break;
}
while (1) {
printf("process_http_request: receiving bytes from server\n");
memset(temp_buffer, 0, TEMP_BUFF_SIZE);
bytes_received = recv(socketfd, temp_buffer, TEMP_BUFF_SIZE, 0);
if (bytes_received == -1) {
if (total_bytes_received == 0) {
printf(
"process_http_request: Data could not be received from socket.\n");
close(socketfd);
return HTTP_ERROR_REC_FAILED;
} else {
printf(
"process_http_request: Timeout waiting for more data.\n");
break;
}
} else if (bytes_received > 0) {
sprintf(http_response_buffer, "%s%s", http_response_buffer,
temp_buffer);
total_bytes_received += bytes_received;
printf("process_http_request: total bytes received = %d\n",
(int) total_bytes_received);
}
if (bytes_received == 0) {
printf("process_http_request: Data receiving finished.\n");
close(socketfd);
break;
}
}
printf("raw buffer=%s", http_response_buffer);
response->raw_response = http_response_buffer;
status = process_http_response(http_response_buffer, response);
if (status == SUCCESS)
printf("process_http_request: HTTP response parsed successfully.\n");
else
printf(
"process_http_request: HTTP response parsing encountered problem. \n");
return status;
}
The problem is that in almost all cases return me a page with 301 redirect and a link .For example for google's ip return me a redirect page to http://www.google.com/ , and I want the page itself and I don't know what to do.
Someone please help.Thank you!

Server closes connection before replying

I'm following the MSDN lessons about TCP/IP client; my issue is that the server isn't replying and the connection closes after I send the Headers.
const char *USR_PORT = "80";
#define BUFF_LEN 512
char recv_buf[BUFF_LEN];
const char HEADER_TO_SEND[] = "HEAD / HTTP/1.1\r\nHost: www.microsoft.com\r\nUser-Agent: RequestHeaderC\r\n\r\n";
{...}
do {
iRes = recv(ConnSocket, recv_buf, BUFF_LEN, 0);
if (iRes > 0)
{
printf("Bytes received: %d\n", iRes);
for (i = 0; (i < iRes) && recv_buf[i] != '\0'; i++)
printf("%c", recv_buf[i]);
}
else if (iRes == 0)
printf("Connection closed by the server.\n");
else printf("Error: %d\n", WSAGetLastError());
} while (iRes > 0);
I'm almost sure the connection was fine as I sent with success the bytes.
I don't receive any byte at all.
The other codes are almost the same as the ones in the tutorial, that's why I haven't posted them. If needed, I will
The server doesn't close the connection immediately if I remove this line:
shutdown(ConnSocket, SD_SEND);
But then I don't get any answer anyways, even if I add
Connection: close\r\n
in the headers
Full code:
const char *USR_PORT = "80";
#define BUFF_LEN 512
char USR_ADDR[] = "www.microsoft.com";
const char HEADER_TO_SEND[] = "HEAD / HTTP/1.1\r\nHost: www.microsoft.com\r\nUser-Agent: RequestHeaderC\r\nConnection: close\r\n\r\n";
int main()
{
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
printf("Error: Wsastartup\n");
exit(1);
}
int iRes;
addrinfo *result, *ptr, addr;
SecureZeroMemory(&addr, sizeof(addr));
addr.ai_family = AF_INET;
addr.ai_protocol = IPPROTO_TCP;
addr.ai_socktype = SOCK_STREAM;
iRes = getaddrinfo(USR_ADDR, USR_PORT, &addr, &result);
if ( iRes != 0 )
{
printf("Error: getaddrinfo");
WSACleanup();
exit(2);
}
SOCKET ConnSocket;
ptr = result;
ConnSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
if (ConnSocket == INVALID_SOCKET)
{
printf("Error: socket: %ld \n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
exit(3);
}
if (connect(ConnSocket, ptr->ai_addr, (int)ptr->ai_addrlen) )
{
closesocket(ConnSocket);
ConnSocket = INVALID_SOCKET;
}
if (ConnSocket == INVALID_SOCKET)
{
printf("Invalid Socket\n");
exit(4);
}
const char *send_buf = HEADER_TO_SEND;
char recv_buf[BUFF_LEN];
if ((iRes = send(ConnSocket, send_buf, strlen(send_buf) - 1, 0)) == SOCKET_ERROR)
{
printf("Error: send\n");
closesocket(ConnSocket);
WSACleanup();
exit(5);
}
int i;
for (i = 0; i < iRes; i++)
printf("%c", send_buf[i]);
printf("Bytes sent: %d\n", iRes);
//if (shutdown(ConnSocket, SD_SEND) == SOCKET_ERROR)
//{
// printf("Error: shutdown: %d\n", WSAGetLastError());
// closesocket(ConnSocket);
// WSACleanup();
// exit(6);
//}
//do {
iRes = recv(ConnSocket, recv_buf, sizeof(recv_buf)-1, 0);
if (iRes > 0)
{
printf("Bytes received: %d\n", iRes);
recv_buf[iRes] = '\0';
for (i = 0; i < iRes; i++)
printf("%c", recv_buf[i]);
}
else if (iRes == 0)
printf("Connection closed by the server.\n");
else printf("Error: %d\n", WSAGetLastError());
//} while (iRes > 0);
getchar();
getchar();
closesocket(ConnSocket);
WSACleanup();
return 0;
}

select() accepting connections while reading and receiving data from clients

I'm connected to certain client then we're communicating. Another client connects to my server which will instantly output that there's a new connection.. e.g Accepting while listening to other clients?.. How can i do that?..
I have already a working one but it only does one thing at a time. When i'm already communicating with my client i can't accept incoming connection or data to other clients. I can only accept new connection or data from other clients when the client i'm communicating is disconnected. how can i do so that it can process both accept and listen to client at the same time. I don't want to use threads.
Here's a part of my code.
do
{
fduse = fdin;
printf("Waiting for Connection\n");
err = select(sMax + 1, &fduse, NULL, NULL, NULL);
if (err < 0)
{
perror(" select() failed");
break;
}
DescRead = err;
for (SockStorage = 0; SockStorage <= sMax && DescRead > 0; ++SockStorage)
{
if (FD_ISSET(SockStorage, &fduse))
{
DescRead -= 1;
if (SockStorage == socketFd)
{
printf(" Listening socket is readable\n");
do
{
NewSFD =
accept(socketFd, (struct sockaddr *)&cli_addr, &clilen);
if (NewSFD < 0)
{
if (errno != EWOULDBLOCK)
{
perror(" accept() failed");
DCSERVER = TRUE;
}
break;
}
if (ClientCount < MAX_CLIENTS)
{
for (loop = 0; loop < MAX_CLIENTS; loop++)
{
if (Clients[loop].connected_sock < 0)
{
Clients[loop].connected_sock = NewSFD;
break;
}
}
ClientCount++;
}
else
{
printf("Maximum Client Reached.\n");
char *sendtoclient = "Server full. ";
send(NewSFD, sendtoclient, strlen(sendtoclient), 0);
close(NewSFD);
break;
}
ip = ntohl(cli_addr.sin_addr.s_addr);
printf(" Connection from %d.%d.%d.%d\n",
(int)(ip >> 24) & 0xff,
(int)(ip >> 16) & 0xff,
(int)(ip >> 8) & 0xff, (int)(ip >> 0) & 0xff);
dlogs(ip);
FD_SET(NewSFD, &fdin);
if (NewSFD > sMax)
sMax = NewSFD;
}
while (NewSFD != -1);
}
else
{
int d;
for (d = 0; d < MAX_CLIENTS; d++)
{
printf("Descriptor ID: %d\n", Clients[d].connected_sock);
}
pfds[0].fd = fd;
pfds[0].events = POLLIN;
pfds[1].fd = SockStorage;
pfds[1].events = POLLIN;
state = FALSE;
do
{
rc = poll(pfds, 2, -1);
if (pfds[0].revents & POLLIN)
{
while ((nbytes = read(fd, buf, sizeof (buf) - 1)) > 0)
{
buf[nbytes] = '\0';
printf("%s\n", buf);
}
pfds[0].events = 0;
pfds[1].events = POLLIN | POLLOUT;
}
if (pfds[1].revents & POLLIN)
{
err = recv(SockStorage, strbuf, sizeof (strbuf), 0);
if (err < 0)
{
if (errno != EWOULDBLOCK)
{
perror(" recv() failed");
state = TRUE;
}
break;
}
if (err == 0)
{
printf(" Connection closed\n");
state = TRUE;
break;
}
dSize = err;
printf(" %d bytes received\n", dSize);
}
if (pfds[1].revents & POLLOUT)
{
int s;
for (s = 0; s < MAX_CLIENTS; s++)
{
if (Clients[s].connected_sock > 0)
{
err =
send(Clients[s].connected_sock, buf,
strlen(buf), 0);
if (err < 0)
{
perror(" send() failed");
track = s;
state = TRUE;
break;
}
}
}
pfds[0].events = POLLIN;
pfds[1].events = POLLIN;
}
}
while (TRUE);
fopen("/sockF.txt", "w");
if (state)
{
ClientCount--;
close(SockStorage);
FD_CLR(SockStorage, &fdin);
if (SockStorage == sMax)
{
while (FD_ISSET(sMax, &fdin) == FALSE)
sMax -= 1;
}
}
}
}
}
} while (DCSERVER == FALSE);
cleanUP(SockStorage, sMax);
}
I've been working on it for two days and still i can't get it. thanks..
Well, to give you an example of a working multi-connection daemon, have a look at this example
If you need a further explanation to go with it, shoot.
Note, the code in that example has been stripped of things like daemon_init(), etc, so just copy-pasting blindly and trying to compile it won't work.
Added setnonblocking() as per request.
void setnonblocking(sock)
int sock;
{
int opts;
opts = fcntl(sock, F_GETFL);
if (opts < 0)
{
syslog(LOG_ERR, "fcntl(F_GETFL) failed");
exit(EXIT_FAILURE);
}
opts = (opts | O_NONBLOCK);
if (fcntl(sock, F_SETFL, opts) < 0)
{
syslog(LOG_ERR, "fcntl(F_SETFL) failed");
exit(EXIT_FAILURE);
}
return;
}
And daemon_init()
int daemon_init(void)
{
pid_t pid;
int i;
if ((pid = fork()) < 0)
{
return -1;
}
else if (pid != 0)
{
exit(0);
}
for (i=getdtablesize();i>=0;--i) close(i);
i = open("/dev/null", O_RDWR); /* open stdin */
dup(i); /* stdout */
dup(i); /* stderr */
setsid();
return 0;
}

Resources