Check latest version here.
Header File 1 for Server Program: SChat_register.h
Header File 2 for Server Program:SChat_connect.h
Server Program: SChat.c
Header File 1 for Server Program: SChat_register.h
#ifndef SCHAT_REGISTER_H #define SCHAT_REGISTER_H //SChat_register.h #include "SChat_connect.h" typedef short bool; int* ar;//= (int*) malloc(sizeof(int)); int maxIndex;// = 0; int top;// = -5; bool reg_lock;// = false; void getRegisteredList(){ int i; for(i=0; i<=top; i++) printf("%d\t", ar[i]); printf("\n"); } //call this before using any other function of this library void init(){ ar = (int*) calloc(1, sizeof(int)); if(ar == NULL) Error("malloc error in init"); top = -1; con_init(); maxIndex = 0; reg_lock = false; } int registerMe(int fd){ printf("registerMe:In registerMe\n"); while(reg_lock) printf("registerMe:reg_lock1 busy\n"); reg_lock = true; printf("registerMe:reg_lock1 taken\n"); int retIndex=-1; if(top == maxIndex){ ar = realloc(ar, (maxIndex+1)*2 * sizeof(int)); if(ar == NULL) Error("realloc error in register"); maxIndex = (maxIndex+1)*2 - 1; } //POS FROM 0 TO top are filled on sorted order already. Use ++top and insert fd. int i; for(i=top; i>0; i--){ if(ar[i] > fd) ar[i+1] = ar[i]; else{ retIndex = i+1; ar[retIndex] = fd; break; } } if(top <1){ ar[top+1] = fd; retIndex = top+1; } ++top; AddCon_num(retIndex); printf("registerMe:reg_lock1 freed\n"); reg_lock = false; return retIndex; } int getFd(int index){ return ar[index]; } int isRegistered(int fd){//returns -1 if not registered else returns non-negative // test for top =0, =1, =n //search fd in sorted array ar using binary search int ans = -1; /* int b=0, e=top; do{ printf("In isRegistered\n"); int mid = (b+e)/2; if(ar[mid] == fd){ ans = mid; break; }else if(ar[mid] > fd) e = mid-1; else b = mid+1; }while(b<e);*/ int i; for(i=0; i<=top; i++){ if(ar[i] == fd){ ans = i; break; } } return ans; } void unRegister(int x){//arg is index if(x== -1) return; int i; for(i=x+1; i<=top; i++){ ar[i-1] = ar[i]; } --top; } void clean(int fd){ while(reg_lock) printf("clean:reg_lock3 busy\n"); reg_lock = true; printf("clean:reg_lock3 taken\n"); int index; if((index = isRegistered(fd)) >= 0){ unConnect(index); unRegister(index); } printf("clean:reg_lock3 freed\n"); reg_lock = false; } //frees dynamic memory void freeRegister(){ printf("In freeRegister\n"); freeConnect(); free(ar); } #endif // SCHAT_REGISTER_H
Header File 2 for Server Program:SChat_connect.h
#ifndef SCHAT_CONNECT_H #define SCHAT_CONNECT_H //SChat_connect.h #define true 1 #define false 0 #include<stdio.h> #include<stdlib.h> #include <string.h> #include "SChat_register.h" void Error(const char *msg){ perror(msg); exit(1); } int **con_ar; int con_num;//it num of clients connected with the server void con_init(){ con_ar = NULL; con_num = 0; } void printConns(){ int i; for(i=0; i<con_num; i++){ int j; for(j=0; j<con_num; j++){ //printf("%d %d\n",i,j); printf("%d\t", con_ar[i][j]); } printf("\n"); } printf("\n"); } void AddCon_num(int ind){ printf("In AddCon_num()\n"); printConns(); ++con_num; con_ar = (int**) realloc(con_ar, con_num*sizeof(int*));//add row at end if(con_ar == NULL && con_num > 0) printf("realloc returns NULL\n"), exit(1); con_ar[con_num-1] = NULL;//initialize last row pointer to NULL //Extend 2D array printf("In AddCon_num(): Row added\n"); int i; for(i=0; i<con_num; i++){//for each row con_ar[i] = (int *) realloc(con_ar[i], con_num*sizeof(int));//add column at end if(con_ar[i] == NULL && con_num > 0) printf("realloc returns NULL\n"), exit(1); } printf("In AddCon_num(): col added\n"); //making space for ind for(i=con_num-1; i>0 ; i--){//for each row int j; for(j=con_num-1; j>=ind; j--)//for each col larger than ind con_ar[i][j] = con_ar[i-1][j]; } for(i=con_num-1; i>0 ; i--){//for each col int j; for(j=con_num-1; j>=ind; j--)//for each row larger than ind con_ar[j][i] = con_ar[i][j-1]; } //initialize ind for(i=0; i<con_num; i++){ con_ar[ind][i] = 0; con_ar[i][ind] = 0; } printConns(); printf("AddCon_num() ENDS\n"); } void DeleteCon_num(int ind){ printf("In DeleteCon_num()\n"); printConns(); int i; for(i=ind+1; i<con_num ; i++){//for each row int j; for(j=ind+1; j<con_num; j++)//for each col con_ar[i-1][j-1] = con_ar[i][j]; } con_num--; for(i=0; i<con_num; i++){ con_ar[i] = (int *) realloc(con_ar[i], con_num*sizeof(int));//del col at end if(con_ar[i] == NULL && con_num > 0) printf("realloc returns NULL\n"), exit(1); } con_ar = (int**) realloc(con_ar, con_num*sizeof(int*));//del row at end if(con_ar == NULL && con_num > 0) printf("realloc returns NULL\n"), exit(1); printConns(); } int connectClients(int fd, int new_fd){//both fds are already registered. Returns 1 if connection accepted else returns 0 printf("In connectClients\n"); //if not yet connected, ask new_fd for connection int fd_ind = isRegistered(fd); int new_fd_ind = isRegistered(new_fd); int res = 0, n; if(con_ar[fd_ind][new_fd_ind] == 0){ char buff[100]; bzero(buff,100); sprintf(buff, "Allow %d to chat y/n?", fd); n=write(new_fd, buff, strlen(buff)); if(n<0) Error("In connectClients: "); bzero(buff,100); n=read(new_fd, buff, 99); if(n<0) Error("In connectClients: "); else if(n==0){ close(new_fd); clean(new_fd);} else if(buff[0] == 'y' || buff[0] == 'Y') res = 1; } if(res == 1){ con_ar[fd_ind][new_fd_ind] = 1; con_ar[new_fd_ind][fd_ind] = 1; printConns(); } return res; } void communicate(int fd, char* msg){//sends msg to all connected to fd printf("In communicate\n"); //write msg to all connections of fd int index = isRegistered(fd); if(index < 0) Error("In communicate: "); int i; for(i=0; i<con_num; i++){ if( con_ar[i][index]==1){ //send msg to ar[i] if( write(getFd(i), msg, strlen(msg)) < 0 ) Error("In communicate: "); } } } // void requestConn(int fd, int fd2){//fd wants to have chat with fd2 char msg[100]; sprintf(msg, "SERVER: %d wants to have chat with you", fd); if( write(fd2, msg, strlen(msg)) < 0 ) Error("In requestConn: "); } //returns 0 if fd is not connected to anyone yet. int isConnected(int fd){ printf("In isConnected\n"); int i, index = isRegistered(fd); for(i=0; i<con_num; i++){ if(i==index) continue; if(con_ar[i][index] == 1) return 1; } return 0; } //disconnect the 2 fds void disConnect(int fd, int fd2){ int ind = isRegistered(fd), ind2 = isRegistered(fd2); con_ar[ind][ind2] = 0; con_ar[ind2][ind] = 0; printConns(); } //disconnects fd if connected to any. void unConnect(int x){//arg is index printf("In unConnect\n"); DeleteCon_num(x); } //frees dynamic memory void freeConnect(){ printf("In freeConnect\n"); int i; for(i=0; i< con_num; i++) free(con_ar[i]); } #endif // SCHAT_CONNECT_H
Server Program: SChat.c
//Server Program #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include "SChat_register.h" #define BACKLOG 1023 int createServerSocket(int port){ int listenfd; struct sockaddr_in servaddr; //STEP1 socket function if((listenfd=socket(AF_INET, SOCK_STREAM, 0)) < 0) Error("ERROR WITH socket function"); //STEP2 address structure bzero((char *) &servaddr, sizeof(servaddr)); servaddr.sin_family=AF_INET; servaddr.sin_port=htons(port); servaddr.sin_addr.s_addr=INADDR_ANY; //STEP3 bind function if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) Error("ERROR WITH bind function"); //STEP4 listen function listen(listenfd, BACKLOG); return listenfd; } int serve(int fd){ printf("\nIn serve\n"); int regisIndex = isRegistered(fd); printf("Registered fds: "); getRegisteredList(); char buff[100], temp[100]; int status=0, rd=0, wr=0; bzero(buff,100); rd = read(fd, buff, 99); if(rd == 0){ clean(fd); printf("Closing connection"); return status; } if(rd < 0){ //Error("read error in serve: "); clean(fd); return status; } if(regisIndex == -1){//if not registered printf("Gonna register now\n"); sscanf(buff, "%s", temp); if(strcmp((temp), "register") != 0){ printf("Closing connection"); return status; } //clean(fd); registerMe(fd); printf("Registered\n"); sprintf(buff, "You are now registered with registration id = %d\n", fd); wr = write(fd, buff, strlen(buff)); if(wr < 0) Error("write error in serve: "); return status=1; }else{//if registered printf("Already registered\n"); sscanf(buff, "%s", temp); int disconn_req = strcmp(temp, "disconnect"); int conn_req = (isConnected(fd) == 0)?strcmp(temp, "connect"):1;//if not already connected, return 1 if(conn_req == 0){//connect request int new_fd; sscanf(buff, "%s %d", temp, &new_fd); if(isRegistered(new_fd) < 0 ){//if new_fd NOT registered sprintf(buff, "No connection exists registered with id = %d\n", new_fd); }else if(isConnected(new_fd) == 1){//new_fd is already connected requestConn(fd, new_fd); sprintf(buff, "%d is already connected with someone. Your request to chat is sent to %d.\n", new_fd, new_fd); }else if(connectClients(fd, new_fd) == 1){//if connection accepted by new_fd sprintf(buff, "%d now connected with %d\n", fd, new_fd); }else{//if connection refused by new_fd sprintf(buff, "Connection refused by %d\n", new_fd); } wr = write(fd, buff, strlen(buff)); if(wr < 0) Error("write error in serve: "); return status=1; }else if(isConnected(fd) == 0){//if not connected to anyone yet sprintf(buff, "Please connect to chat\n", fd); wr = write(fd, buff, strlen(buff)); if(wr < 0) Error("write error in serve: "); return status=1; }else if(disconn_req == 0){//if disconn request int new_fd; sscanf(buff, "%s %d", temp, &new_fd); if(isRegistered(new_fd) < 0 ){//if new_fd NOT registered sprintf(buff, "No connection exists registered with id = %d\n", new_fd); }else{//if there is a connection disConnect(fd ,new_fd); sprintf(buff, "You and %d are now DISCONNECTED OR there was no connection.\n", new_fd); } wr = write(fd, buff, strlen(buff)); if(wr < 0) Error("write error in serve: "); return status=1; }else{//if already connected, send msg communicate(fd, buff); } } } int main(int argc, char** argv){ int port, listenfd, nfds, temp_fd; fd_set temp_fds, rfds; struct sockaddr_in cli_addr; if(argc != 2 || (port=atoi(argv[1])) < 1024)//test 1. 2.abbc 3.9041abc 4.+abc 5.-abc 6.1024 7.9041 Error("ERROR WITH ARGS- Usage: ./a.out <portNumber 1024+ >"); listenfd = createServerSocket(port); nfds = getdtablesize(); FD_ZERO(&temp_fds); FD_SET(listenfd, &temp_fds); init(); while(1){ memcpy(&rfds, &temp_fds, sizeof(rfds)); if(select(nfds, &rfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0) < 0) Error("select"); if(FD_ISSET(listenfd, &rfds)) { int connfd, alen = sizeof(cli_addr); connfd = accept(listenfd, (struct sockaddr *)&cli_addr, &alen); if(connfd < 0) error("accept "); FD_SET(connfd, &temp_fds); nfds = (connfd>nfds)?connfd:nfds; } for(temp_fd=0; temp_fd <= nfds; ++temp_fd) if(temp_fd != listenfd && FD_ISSET(temp_fd, &rfds)) if(serve(temp_fd) == 0) { (void) close(temp_fd); FD_CLR(temp_fd, &temp_fds); } } close(listenfd); freeRegister(); return 0; }Client Program: CChat.c
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> void error(const char *msg) { perror(msg); exit(0); } int main(int argc, char *argv[]) { int sockfd, n, max_fd; fd_set rd_set, wr_set, temp_rd_set; struct sockaddr_in serv_addr; struct hostent *server; char exit_str[5] = "exit"; char buffer[256]; if (argc < 3) { fprintf(stderr,"usage %s hostname port\n", argv[0]); exit(0); } //STEP1 socket function sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) error("ERROR opening socket"); server = gethostbyname(argv[1]); if (server == NULL) { fprintf(stderr,"ERROR, no such host\n"); exit(0); } //STEP2 prepare address structure bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length); serv_addr.sin_port = htons(atoi(argv[2])); //STEP3 connect function: request to server for connection if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) error("ERROR connecting"); max_fd = (sockfd>fileno(stdin))?sockfd:fileno(stdin); //FD_ZERO(&wr_set); FD_ZERO(&rd_set); // FD_SET(sockfd, &wr_set); FD_SET(sockfd, &temp_rd_set); FD_SET(fileno(stdin), &temp_rd_set); //STEP4 read and write to server. while(1){ memcpy(&rd_set, &temp_rd_set, sizeof(rd_set)); if(select( max_fd+1, &rd_set, (fd_set *)NULL, (fd_set *)NULL, (struct timeval*)NULL)<0) error("in select: "); if(FD_ISSET(sockfd, &rd_set)){ //printf("CLIENT: sockfd is readable.\n"); bzero(buffer,256); n = read(sockfd,buffer,255);//read from server and save it in array buffer if (n < 0) error("ERROR reading from socket"); printf("%s\n",buffer);//write to stdout the buffer's contents } if(FD_ISSET(fileno(stdin), &rd_set)){ //printf("CLIENT: stdin is readable.\n"); bzero(buffer,256); fgets(buffer,255,stdin);//read from client stdin if(bcmp(exit_str, buffer, 4)==0){ close(sockfd); return 0; } n = write(sockfd,buffer,strlen(buffer));//write to server if (n < 0) error("ERROR writing to socket"); } } close(sockfd); return 0; }Cheers. Please leave a comment for any bug or issue!
Can you show to how execute the program? as i tried but the client is not getting registred
ReplyDelete