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