?? s.c
字號:
/* s.c A chat server by Ze Zhang and Johannes Detlefsen compile: gcc -o s s.c list.c -lpthread*/#include <stdio.h>#include <stdlib.h> // for atoi() function#include <sys/socket.h>#include <sys/types.h>#include <errno.h>#include <netdb.h>#include <string.h>#include <sys/wait.h>#include <pthread.h> // for the cosy POSIX threads#include <arpa/inet.h> // for inet_ntoa() function#include <fcntl.h>#include <unistd.h>#include <sys/msg.h>#include "list.h" // linked list to save socket file descriptors in it#define BACKLOG 10 // connections on the queue#define MAXDATALEN 1024#define PORT 9034/*initialize list*/ List L; //Position P; //better declare local pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;void * server(void * arg);int main( int argc, char *argv[] ) { int sockfd,new_fd; // listen on sock_fd, new connection on new_fd int portnum; struct sockaddr_in server_addr; struct sockaddr_in client_addr; int sin_size; pthread_t thread_id; int sfd; /* socket file descriptor in the linked list*/ Position P; /*check if portnumber is received by argument, if not use defined */ if( argc == 2 ) portnum = atoi(argv[1]); else portnum = PORT; /*set up linked list to store the socket file descriptors */ L = MakeEmpty( NULL ); P = Header( L ); if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } /* initialize the server_addr */ server_addr.sin_family=AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; // here we get our IP address of www.tec.hkr.se server_addr.sin_port=htons(portnum); memset(&(server_addr.sin_zero), '\0', 8); // zero the rest of the struct /* bind the port to the socket */ if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))== -1) { perror("bind"); exit(1); } /* listen if anyone connecting to the port*/ if (listen(sockfd, BACKLOG) == -1) { perror("listen"); exit(1); } else printf("server is running now!\nPlease exit after all connections closed with Ctrl-c \n"); while(1){ sin_size=sizeof(struct sockaddr_in); if ((new_fd = accept(sockfd, (struct sockaddr *)&client_addr,&sin_size)) == -1) { perror("accept"); continue; } printf("new connection accepted\n"); /* store new file descriptors in linked list */ //sfd=new_fd; pthread_mutex_lock(&mutex); printf("mutex lock aquired for INSERT\n"); P = Header( L ); Insert( new_fd, L, P ); //printf("Inserted sfd -%d- on the list\n",sfd); P = Advance( P ); //go to next one PrintList( L ); pthread_mutex_unlock(&mutex); printf("mutex INSERT unlock\n"); printf("server got connection from %s\n",inet_ntoa(client_addr.sin_addr)); pthread_create(&thread_id,NULL,server,(void*)&new_fd); // pthread_join(thread_id,NULL); say: thread attribute is detached!!! pthread_detach(thread_id); /* now we never ever have to wait for this one anymore it's easier (less code) do change a joinable thread into detached state than creating a detached thread... */ } DeleteList( L ); // clean up linked list close(sockfd); // close Socket}/*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx** Server function starts for every connected Client**xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/void * server(void * arg){ int msglen; char *buffer =(char *) malloc(MAXDATALEN), *msg =(char *) malloc(MAXDATALEN), *termmsg=(char *) malloc(30); char dpchar[]=": ", *strp; char usrname[10]; int ts_fd,termlen; ts_fd = * (int *) arg; /* get thread-socket file descriptor*/ int sfd; /* socket file descriptor in the linked list*/ Position P; if(recv(ts_fd,usrname,MAXDATALEN,0) == -1){ printf("error: could not recv usrname!\n"); exit(1); } else printf("%s connected to the server\n",usrname); while(1){ recv(ts_fd,buffer,MAXDATALEN,0); /* termination control */ if ( strncmp( buffer, "/q", 2) == 0 ){ printf("%s has left the chat\n",usrname); strcpy(termmsg,usrname); strp=termmsg; strp=strp+(strlen(termmsg)); strcpy(strp," has left the chat"); termlen=strlen(termmsg); pthread_mutex_lock(&mutex); printf("mutex lock aquired for DELETE\n"); Position P = Header( L ); do{ // delete socket file descriptor from linked list P = Advance( P ); sfd = Retrieve( P ); //read from list! if(sfd == ts_fd) Delete( sfd, L ); if(sfd != ts_fd) send(sfd,termmsg,termlen,0); } while( !IsLast( P, L ) ); PrintList( L ); /*if( IsEmpty( L ) ){ L = MakeEmpty( NULL ); P = Header( L ); }*/ pthread_mutex_unlock(&mutex); printf("mutex DELETE unlock \n"); close(ts_fd); break; } strcpy(msg,usrname); strp=msg; strp=strp+(strlen(msg)); strcpy(strp,dpchar); strp+=2; // move pointer 2 forward because dpchar contains ": " strcpy(strp,buffer); msglen=strlen(msg); //if(send(ts_fd,msg,msglen,0)>0) printf("msg -%s- send\n",msg); /* send msg to all clients: */ pthread_mutex_lock(&mutex); printf("mutex lock aquired for SEND\n"); Position P = Header( L ); do{ P = Advance( P ); sfd = Retrieve( P ); //read from list! //if(sfd != ts_fd) send(sfd,msg,msglen,0); } while( !IsLast( P, L ) ); PrintList( L ); pthread_mutex_unlock(&mutex); printf("mutex SEND unlock\n"); }; return 0;}/* Is the linked list a CRITICAL SECTION indeed? Do we need to protect the linked list with MUTEX, CONDVAR or Semaphores ?*/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -