Skip to content

Commit efe6ed4

Browse files
committed
Exercise 6, timer part remaining.
1 parent 66607fb commit efe6ed4

File tree

10 files changed

+545
-0
lines changed

10 files changed

+545
-0
lines changed

Exercises/Exercise6/Makefile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
all: server client
2+
server: server.c server.h helper.c helper.h hashtable.c hashtable.h
3+
gcc -o server server.c helper.c hashtable.c
4+
5+
client: client.c helper.c helper.h
6+
gcc -o client client.c helper.c
7+
8+
clean:
9+
rm server client

Exercises/Exercise6/Problem.pdf

246 KB
Binary file not shown.

Exercises/Exercise6/README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Concurrent TCP Server using signal-driven I/O
2+
3+
### Task Requirement:
4+
Write a program [webserver.c](./webserver.c) using which works in the following way:
5+
- It
6+
7+
- Establish signal handler for SIGIO using `signal()` and `sigaction()`
8+
- Set socket owner. `fcntl()` with `F_SETOWN`. It tells who will receive signals
9+
- `fcntl(fd, F_SETOWN, getpid());`
10+
- Enable signal driven I/O for the socket using `O_ASYNC`
11+
- Make connection sockets to be non-blocking bcz u get edge-triggered notifications. So you have to read all available data by performs I/O system calls until a call fails with the error `EAGAIN` or `EWOULDBLOCK`.
12+
- use `O_NONBLOCK` flag.
13+
- `fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_ASYNC | O_NONBLOCK);`
14+
- Specify a realtime signal to be used in place of SIGIO to avoid queuing and handling multiple connections.
15+
- Use `SA_SIGINFO` flag in `sigaction()` to establish handler for RT signals.
16+
### Server performance
17+
18+
### Demo Run
19+
20+
### Dependencies:
21+
22+
### Instructions to run:
23+

Exercises/Exercise6/client.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include "helper.h"
2+
3+
#define BUFFERSIZE 128
4+
5+
int main(void)
6+
{
7+
int sockfd = 0;
8+
struct sockaddr_in serverAddr;
9+
10+
/* Create a socket first */
11+
sockfd = Socket(AF_INET, SOCK_STREAM, 0);
12+
13+
/* Initialize sockaddr_in data structure */
14+
serverAddr.sin_family = AF_INET;
15+
serverAddr.sin_port = htons(8004); // port
16+
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
17+
18+
/* Attempt a connection */
19+
if(connect(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0){
20+
errorExit("connect");
21+
}
22+
23+
char buf[BUFFERSIZE];
24+
strcpy(buf, "hello server\n");
25+
Write(sockfd, buf, strlen(buf));
26+
sleep(10);
27+
close(sockfd);
28+
return 0;
29+
}

Exercises/Exercise6/hashtable.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#include "hashtable.h"
2+
3+
int hash(int fd){
4+
return fd % TABLE_SIZE;
5+
}
6+
/**
7+
* @brief initialize a hash table
8+
*/
9+
void initTable(hashTable table) {
10+
11+
if (table == NULL) {
12+
errorExit("HASH table allocation error");
13+
}
14+
for (int i = 0; i < TABLE_SIZE; i++) {
15+
table[i].present = false;
16+
table[i].cliInfo = NULL;
17+
}
18+
}
19+
20+
void insertInTable(hashTable table, int fd, clientNode *clInfo){
21+
// printf("Inserting entry for %d in table\n", fd);
22+
int hashValue;
23+
hashValue = hash(fd);
24+
// printf("hash is %d\n", hashValue);
25+
// printf("is cliInfo null? %s\n", (clInfo == NULL) ? "Yeah" : "Hell no" );
26+
int probeNum = 1;
27+
28+
while (table[hashValue].present == true) {
29+
if(table[hashValue].fd == fd) //updating a key's value instead inserting a new one
30+
break;
31+
hashValue = (hashValue + probeNum * probeNum) % TABLE_SIZE;
32+
probeNum++;
33+
}
34+
35+
table[hashValue].present = true;
36+
table[hashValue].fd = fd;
37+
table[hashValue].cliInfo = clInfo;
38+
}
39+
40+
/**
41+
* @brief search a string in the hash table
42+
*
43+
* @return int : hash value else -1 if fd not found
44+
*/
45+
46+
clientNode *searchTable(hashTable table, int fd) {
47+
// printf("Searching in hashtable for %d\n", fd);
48+
int hashValue = hash(fd);
49+
// printf("hash is %d\n", hashValue);
50+
int probeNum = 1;
51+
while (table[hashValue].present == true)
52+
{
53+
if (table[hashValue].fd == fd) {
54+
return table[hashValue].cliInfo;
55+
}
56+
hashValue = (hashValue + probeNum * probeNum) % TABLE_SIZE;
57+
probeNum++;
58+
}
59+
return CLIENT_DNE;
60+
}
61+
62+
void removeFromTable(hashTable table, int fd){
63+
int hashValue = hash(fd);
64+
int probeNum = 1;
65+
while (table[hashValue].present == true)
66+
{
67+
if (table[hashValue].fd == fd) {
68+
table[hashValue].present = false;
69+
return;
70+
}
71+
hashValue = (hashValue + probeNum * probeNum) % TABLE_SIZE;
72+
probeNum++;
73+
}
74+
}

Exercises/Exercise6/hashtable.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#ifndef HASHTABLE_H
2+
#define HASHTABLE_H
3+
4+
#include "helper.h"
5+
6+
#define PRIME 119
7+
#define TABLE_SIZE 67
8+
#define MAX_LEXEME_LEN 100
9+
#define CLIENT_DNE NULL
10+
11+
typedef struct {
12+
int fd;
13+
clientNode *cliInfo;
14+
bool present;
15+
} hashElem;
16+
17+
typedef hashElem hashTable[TABLE_SIZE];
18+
19+
void initTable(hashTable table);
20+
21+
int hash(int fd);
22+
23+
clientNode *searchTable(hashTable table, int fd);
24+
25+
void insertInTable(hashTable table, int fd, clientNode *clInfo);
26+
27+
void removeFromTable(hashTable table, int fd);
28+
#endif

Exercises/Exercise6/helper.c

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#include "helper.h"
2+
3+
void errorExit(char *msg){
4+
perror(msg);
5+
exit(EXIT_FAILURE);
6+
}
7+
8+
int Socket(int domain, int type, int protocol){
9+
10+
int sockfd = socket(domain, type, protocol);
11+
12+
if( sockfd < 0){
13+
errorExit("socket failed");
14+
}
15+
16+
return sockfd;
17+
}
18+
19+
20+
int Listen(int sockfd, int backlog){
21+
if(listen(sockfd, backlog) < 0){
22+
errorExit("listen failed");
23+
}
24+
25+
return SUCCESS;
26+
}
27+
28+
int Bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen){
29+
if(bind(sockfd, addr, addrlen) < 0){
30+
errorExit("bind failed");
31+
}
32+
33+
return SUCCESS;
34+
}
35+
36+
int Accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen){
37+
int connfd = accept(sockfd, addr, addrlen);
38+
if( connfd < 0){
39+
errorExit("accept failed");
40+
}
41+
42+
return connfd;
43+
}
44+
45+
ssize_t Read(int fd, void *buf, size_t count){
46+
int numRead = read(fd, buf, count);
47+
if( numRead < 0){
48+
if(errno != ECONNRESET && errno != EBADF)
49+
errorExit("read failed");
50+
}
51+
52+
return numRead;
53+
}
54+
55+
ssize_t Write(int fd, const void *buf, size_t count){
56+
int numWritten = write(fd, buf, count);
57+
58+
if(numWritten < 0){
59+
if(errno != EWOULDBLOCK && errno != EAGAIN){
60+
if(errno != ECONNRESET && errno != EBADF)
61+
errorExit("write failed");
62+
}
63+
}
64+
65+
return numWritten;
66+
}
67+
68+
int Close(int fd){
69+
if(close(fd) < 0 ){
70+
if(errno != EBADF)
71+
errorExit("close failed");
72+
}
73+
74+
return SUCCESS;
75+
}
76+
77+
char *getTimestamp(){
78+
char *buf = (char*)malloc(sizeof(char) * 1000);
79+
time_t now = time(0);
80+
81+
struct tm tm = *gmtime(&now);
82+
strftime(buf, sizeof buf, "%a, %d %b %Y %H:%M:%S %Z", &tm);
83+
84+
return buf;
85+
}

Exercises/Exercise6/helper.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#ifndef HELPER_H
2+
#define HELPER_H
3+
4+
#include <sys/types.h>
5+
#include <sys/stat.h>
6+
#include <fcntl.h>
7+
#include <sys/msg.h>
8+
#include <sys/ipc.h>
9+
#include <sys/socket.h>
10+
#include <sys/epoll.h>
11+
#include <stdio.h>
12+
#include <stdlib.h>
13+
#include <unistd.h> // for read() / write()
14+
#include <errno.h>
15+
#include <pthread.h>
16+
#include <string.h>
17+
#include <ctype.h>
18+
#include <netinet/in.h>
19+
#include <arpa/inet.h>
20+
21+
#define SUCCESS 1
22+
23+
/* Client info */
24+
typedef enum {false, true} bool;
25+
26+
typedef struct clientNode{
27+
int fd;
28+
struct clientNode *nextClient;
29+
struct clientNode *prevClient; /* stored to perform deletion in O(1)*/
30+
} clientNode;
31+
32+
typedef struct clientsInfo{
33+
int numClients;
34+
clientNode *firstClient;
35+
clientNode *lastClient;
36+
} clientsInfo;
37+
38+
/* Exit on system call error function*/
39+
void errorExit(char *msg);
40+
41+
void errorExitPthread(char *msg, int errnum);
42+
43+
/* Socket functions */
44+
45+
int Socket(int domain, int type, int protocol);
46+
47+
int Listen(int sockfd, int backlog);
48+
49+
int Bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
50+
51+
int Accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
52+
53+
int Open(const char *pathname, int flags);
54+
55+
ssize_t Read(int fd, void *buf, size_t count);
56+
57+
ssize_t Write(int fd, const void *buf, size_t count);
58+
59+
int Close(int fd);
60+
61+
char *getTimestamp();
62+
63+
#endif

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy