ورود

View Full Version : برنامه چت سرور با C



tazekaram
پنج شنبه 11 مرداد 1386, 00:41 صبح
سلام

مشخص نیست GetUser ,lengthafterchar کد زیر یک برنامه چت سرور می باشد اما دو تابع آن

ها از ساختار استفاده شده)User و تکنیکش هم اینه که برای )

? روهم توضیح بده که چیکار می کنهProcess از اساتید کسی می تونه اونارو بنویسه و تابع

رو طوری تغییر بده که فقط پیام ها بین کلاینت ها رد و بدل بشه؟؟؟؟؟؟؟؟؟؟؟؟؟Process یا اینکه تابع







int ListenConnection(int port);
int CheckSocketRead(int sockfd);
int AcceptClient(int sockfd);
int CheckClientData();
int ReadClientData(UsersConnectionsPTR *sConnection);
int Quit(UsersConnectionsPTR *sConnection, char *sReason);
int Process(UsersConnectionsPTR *sConnection, char *sData);
int SendALL(UsersConnectionsPTR *sConnection, UsersConnectionsPTR *sFrom, char *sMsg);
void handle_signal(int signum);
int CheckSocketWrite(int sockfd);
UsersConnections *UsersConnectionsInsert(UsersConnectionsPTR *sPtr, int sFd, char *sIP);
Users *Insert(UsersPTR *sPtr,UsersConnectionsPTR *sConnection, char *sNick);
void UsersDelete(UsersPTR *sPtr);
void UsersConnectionsDelete(UsersConnectionsPTR *sPtr);
////////////////////////////////////////////////////////////////////
struct UsersConnections;
typedef struct UsersConnections UsersConnections;
typedef UsersConnections *UsersConnectionsPTR;
struct Users;
typedef struct Users Users;
typedef Users *UsersPTR;
// List of users connections to server
struct UsersConnections {
int sockfd;
char IP[16];
UsersPTR User;
struct UsersConnections *Prev;
struct UsersConnections *Next;
};
UsersConnectionsPTR UsersConnectionsStart;
// List of users information
struct Users {
UsersConnectionsPTR Connection;
int status;
char Nick[36];
struct Users *Prev;
struct Users *Next;
};
UsersPTR UsersStart;
int running;
////////////////////////////////////////////////////////////////////int main() {
int clientfd;
pid_t pid;
UsersStart = NULL;
UsersConnectionsStart = NULL;
running = 1;
signal (SIGSEGV, handle_signal);
signal (SIGINT, handle_signal);
signal (SIGUSR1, handle_signal);
signal (SIGUSR2, handle_signal);
signal (SIGPIPE, SIG_IGN);
// Listen for connections on port 9000
clientfd = ListenConnection(9000);
if(!(pid = fork())) {
pid=getpid();
// loop while running = 1
while(running) {
// Check for new client connections
if (CheckSocketRead(clientfd) > 0) {
// Accept the connection and add user to client list
AcceptClient(clientfd);
}
// Check for any incomming data from clients
CheckClientData();
// this is a temp solution to save cpu resources
usleep(200);
}
}
}//main
////////////////////////////////////////////////////////////////////
int ListenConnection(int port) {
int sockfd;
struct sockaddr_in myaddr;
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = INADDR_ANY;
myaddr.sin_port = htons(port);
memset(myaddr.sin_zero, 0, sizeof(myaddr.sin_zero));
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
if (bind(sockfd, (struct sockaddr *)&myaddr, sizeof(struct sockaddr)) == -1) {
perror("bind");
exit(1);
}
// This will listen to the port but we need another function to check this
if (listen(sockfd, 100) == -1) {
perror("listen");
exit(1);
}
return sockfd;
}
////////////////////////////////////////////////////////////////////
int CheckSocketRead(int sockfd) {
int rc;
struct timeval tv;
fd_set read_fd;
tv.tv_sec=0;
tv.tv_usec=1;
FD_ZERO(&read_fd);
FD_SET(sockfd, &read_fd);
rc = select(sockfd+1, &read_fd, NULL, NULL, &tv);
FD_ZERO(&read_fd);
return rc;
}
////////////////////////////////////////////////////////////////////
int AcceptClient(int sockfd) {
int newfd, sinsize;
struct sockaddr_in clientaddr;
UsersPTR From;
UsersConnectionsPTR Connection;
sinsize = sizeof(struct sockaddr_in);
newfd = accept(sockfd, (struct sockaddr *)&clientaddr, &sinsize);
if (newfd == -1) {
// you don't realy want to exit here as it's only 1 client that can't be accepted
// however you will be required to investigate why accept returned -1
perror("accept");
exit(1);
} else if (newfd) {
printf("New CLIENT connection from IP %s on socket %d\n", \
inet_ntoa(clientaddr.sin_addr), newfd);
// Enable non-blocking socket for select()
fcntl(newfd, F_SETFL, O_NONBLOCK);
// Add user to connection list (This function is not in the example, please see
// http://www.devforge.net/downloads/chatserver-tutorial-v0.1.tar.gz
Connection = UsersConnectionsInsert(&UsersConnectionsStart, newfd, \
inet_ntoa(clientaddr.sin_addr));
// Add user to client list (This function is not in the example, please see
// http://www.devforge.net/downloads/chatserver-tutorial-v0.1.tar.gz
Connection->User = UsersInsert(&UsersStart, &Connection, "");
}
}
////////////////////////////////////////////////////////////////////
int CheckClientData() {
int rc, max;
struct timeval tv;
UsersConnectionsPTR Connection, Next;
char output[1024];
fd_set usersfd;
tv.tv_sec=0;
tv.tv_usec=0;
Connection = UsersConnectionsStart;
while (Connection != NULL) {
Next = Connection->Next;
FD_ZERO(&usersfd);
FD_SET(Connection->sockfd, &usersfd);
errno = 0;
rc = select(Connection->sockfd+1, &usersfd, NULL, NULL, &tv);
if (rc > 0) {
ReadClientData(&Connection);
} else if (rc == -1) {
sprintf(output,"%m\n",errno);
Quit(&Connection, output);
}
Connection = Next;
}
}
////////////////////////////////////////////////////////////////////
int ReadClientData(UsersConnectionsPTR *sConnection) {
int i, ch, rc;
char data[1024], output[1024], buffer[1024];
UsersConnectionsPTR Connection;
UsersPTR From;
Connection = *sConnection;
From = (*sConnection)->User;
*buffer='\0';
while (1) {
*data = '\0';
memset(data, 0, sizeof data);
errno = 0;
rc = recv(Connection->sockfd,data,1,0);
data[rc] = '\0';
if (errno) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
sprintf(output,"%m\n",errno);
Quit(&Connection, output);
return;
}
} else if (rc > 0) {
ch = data[0];
if (ch != '\n' && ch != '\r') {
sprintf(buffer,"%s%c",buffer,ch);
} else if (ch != '\r') {
Process(&Connection, buffer);
*buffer='\0';
break;
}
} else if (rc == 0) {
// closed successfully
Quit(&Connection, "Disconnected");
return;
} else {
// connection terminated
Quit(&Connection, "Connection terminated");
return;
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
int Quit(UsersConnectionsPTR *sConnection, char *sReason) {
char buffer[1024];
UsersPTR From;
UsersConnectionsPTR Connection;
Connection = *sConnection;
From = (*sConnection)->User;
// close file descriptor
close(Connection->sockfd);
// Delete user (This function is not in the example, please see
// http://www.devforge.net/downloads/chatserver-tutorial-v0.1.tar.gz
UsersDelete(&From);
// Delete connection (This function is not in the example, please see
// http://www.devforge.net/downloads/chatserver-tutorial-v0.1.tar.gz
UsersConnectionsDelete(&Connection);
}
////////////////////////////////////////////////////////////////////
int Process(UsersConnectionsPTR *sConnection, char *sData)
{
int i;
char action[36], buffer[1024], temp[36];
UsersConnectionsPTR Connection;
UsersPTR From, To, currentPtr;
*buffer='\0';
Connection = *sConnection;
From = (*sConnection)->User;
if (lengthafterchar(&sData[0], ' ')) {
snprintf(action,lengthafterchar(&sData[0], ' '),&sData[0]);
i = lengthafterchar(&sData[0], ' ');
} else {
strcpy(action,&sData[0]);
}
if (From->status) {
if (!lengthafterchar(&sData[0], ' ')) {
SendMSG(Connection->sockfd, "Unknown command\n");
// Global messages to all authorized users
} else if (strcasecmp(action,"GLOBAL")==0) {
if (!lengthafterchar(&sData[0], ' ')) {
SendMSG(Connection->sockfd, "Incorrect syntax for command GLOBAL: GLOBAL MESSAGE\n");
} else {
sprintf(buffer,"GLOBAL %s %s\n",From->Nick, &sData[i]);
printf("<%s> GLOBAL %s\n",From->Nick, &sData[i]);
SendALL(&UsersConnectionsStart, &Connection, buffer);
}
// Private messages to other users
} else if (strcasecmp(action,"MSG")==0) {
if (!lengthafterchar(&sData[0], ' ')) {
SendMSG(Connection->sockfd, "Incorrect syntax for command MSG: MSG NICK MESSAGE\n");
} else {
snprintf(temp,lengthafterchar(&sData[i], ' '),&sData[i]);
i = i + lengthafterchar(&sData[i], ' ');
To = GetUser(&UsersStart, temp);
if (To != NULL) {
sprintf(buffer,"MSG %s %s\n",From->Nick, &sData[i]);
printf("<%s> MSG %s %s\n",From->Nick, To->Nick, &sData[i]);
SendMSG(To->Connection->sockfd, buffer);
} else {
sprintf(buffer,"No such nick %s\n",temp);
SendMSG(Connection->sockfd, buffer);
}
}
} else {
SendMSG(Connection->sockfd, "Unknown command\n");
}
} else if (strcasecmp(action,"NICK")==0) {
if (GetUser(&UsersStart, &sData[i]) != NULL) {
SendMSG(Connection->sockfd, "Nickname is already in use, please try another.\n");
} else {
strcpy(From->Nick, &sData[i]);
From->status = 1;
sprintf(buffer,"Welcome %s\n",From->Nick);
SendMSG(Connection->sockfd, buffer);
sprintf(buffer,"CONNECTED %s\n",&sData[i]);
printf("%s",buffer);
SendALL(&UsersConnectionsStart, &Connection, buffer);
}
} else {
SendMSG(Connection->sockfd, "You must select a nick by typing: NICK yournickname\n");
}
}
////////////////////////////////////////////////////////////////////
int SendALL(UsersConnectionsPTR *sConnection, UsersConnectionsPTR *sFrom, char *sMsg) {
UsersConnectionsPTR Connection, nextPtr, currentPtr;
UsersPTR From;
currentPtr = *sConnection;
From = (*sFrom)->User;
while (currentPtr != NULL) {
nextPtr = currentPtr->Next;
if (strcasecmp(currentPtr->User->Nick,From->Nick)!=0 && currentPtr->User->status > 0) {
SendMSG(currentPtr->sockfd, sMsg);
}
currentPtr = nextPtr;
}
}
int SendMSG(int sockfd, char *msg) {
return send(sockfd, msg, strlen(msg), 0);
}
////////////////////////////////////////////////////////////////////
void handle_signal(int signum) {
// This will require you to research more on signal handling
printf("SIGNAL %d\n", signum);
if (signum == 11 || signum == 2) exit(0);
}
////////////////////////////////////////////////////////////////////
int CheckSocketWrite(int sockfd) {
int rc;
struct timeval tv;
fd_set write_fd;
tv.tv_sec=0;
tv.tv_usec=1;
FD_ZERO(&write_fd);
FD_SET(sockfd, &write_fd);
rc = select(sockfd+1, NULL, &write_fd, NULL, &tv);
FD_ZERO(&write_fd);
return rc;
}
////////////////////////////////////////////////////////////////////
UsersConnections *UsersConnectionsInsert(UsersConnectionsPTR *sPtr, int sFd, char *sIP) {
UsersConnectionsPTR newPtr, previousPtr, currentPtr, nextPtr;
newPtr = (UsersConnections *) malloc(sizeof(UsersConnections));
if (newPtr != NULL) {
strcpy(newPtr->sockfd, sFd);
strcpy(newPtr->IP, sIP);
currentPtr = *sPtr;
nextPtr = currentPtr->Next;
newPtr->Next = currentPtr;
newPtr->Prev = NULL;
if (currentPtr != NULL) {
currentPtr->Prev = newPtr;
}
*sPtr = newPtr;
return newPtr;
} else {
printf("\n\nmalloc error: out of memory\n\n");
return NULL;
}
}
////////////////////////////////////////////////////////////////////
Users *Insert(UsersPTR *sPtr,UsersConnectionsPTR *sConnection, char *sNick)
{
UsersPTR newPtr, previousPtr, currentPtr, nextPtr;
newPtr = (Users *) malloc(sizeof(Users));
if (newPtr != NULL) {
strcpy(newPtr->UsersConnectionsPTR, sConnection);
strcpy(newPtr->Nick, sNick);
currentPtr = *sPtr;
nextPtr = currentPtr->Next;
newPtr->Next = currentPtr;
newPtr->Prev = NULL;
if (currentPtr != NULL) {
currentPtr->Prev = newPtr;
}
*sPtr = newPtr;
return newPtr;
} else {
printf("\n\nmalloc error: out of memory\n\n");
return NULL;
}
}
////////////////////////////////////////////////////////////////////
void UsersDelete(UsersPTR *sPtr)
{
UsersPTR previousPtr, nextPtr, currentPtr, tempPtr;
tempPtr = *sPtr;
previousPtr = (*sPtr)->Prev;
nextPtr = (*sPtr)->Next;
if (previousPtr == NULL) {
if (nextPtr != NULL) {
*sPtr = nextPtr;
(*sPtr)->Prev = NULL;
} else {
*sPtr = NULL;
}
} else {
if (nextPtr != NULL) {
previousPtr->Next = nextPtr;
nextPtr->Prev = previousPtr;
} else {
previousPtr->Next = NULL;
}
}
free(tempPtr);
}

////////////////////////////////////////////////////////////////////
void UsersConnectionsDelete(UsersConnectionsPTR *sPtr)
{
UsersConnectionsPTR previousPtr, nextPtr, currentPtr, tempPtr;
tempPtr = *sPtr;
previousPtr = (*sPtr)->Prev;
nextPtr = (*sPtr)->Next;
if (previousPtr == NULL) {
if (nextPtr != NULL) {
*sPtr = nextPtr;
(*sPtr)->Prev = NULL;
} else {
*sPtr = NULL;
}
} else {
if (nextPtr != NULL) {
previousPtr->Next = nextPtr;
nextPtr->Prev = previousPtr;
} else {
previousPtr->Next = NULL;
}
}
free(tempPtr);
}
////////////////////////////////////////////////////////////////////
//int Process(UsersConnectionsPTR *sConnection, char *sData);
//int i=lengthafterchar(&sData[0], ' ');
//UsersPTR To = GetUser(&UsersStart, temp);
//char temp[36];
//UsersPTR UsersStart;