Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdlib.h>
- #include <stdio.h>
- #include <pthread.h>
- #include <fcntl.h>
- #include <netdb.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <unistd.h>
- #include <string.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- char buffer[512];
- int chatLog_fd = 0;
- int max_fd;
- int chat_count = 0;
- pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;
- fd_set all_fds;
- void * chatDaemon(void * fd);
- void * consoleDaemon(void * n);
- void *get_in_addr(struct sockaddr *sa);
- void grabMutex();
- void releaseMutex();
- int main (int argc, char **argv) {
- struct addrinfo *result,
- hint,
- *pointer;
- struct sockaddr_storage remoteHost;
- socklen_t addrlen;
- int listen_fd,
- value,
- new_fd,
- i;
- pthread_t chat[100];
- char remoteIP[INET6_ADDRSTRLEN];
- memset(&hint, 0, sizeof(hint));
- hint.ai_family = AF_UNSPEC;
- hint.ai_socktype = SOCK_STREAM;
- hint.ai_flags = AI_PASSIVE;
- /**
- * Set-up for receiving addresses
- */
- if (value = (getaddrinfo(NULL, "2000", &hint, &result)) != 0) {
- fprintf(stderr, "Selecting port: %s\n", gai_strerror(value));
- exit(1);
- }
- value = 1;
- FD_ZERO(&all_fds); //Zero out the fd containers
- for (pointer = result; pointer != NULL; pointer = pointer->ai_next) {
- listen_fd = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
- if (listen_fd < 0)
- continue;
- setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int));
- if (bind(listen_fd, pointer->ai_addr, pointer->ai_addrlen) < 0) {
- close(listen_fd);
- continue;
- }
- break;
- } //Get a suitable port
- if (pointer == NULL) {
- fprintf(stderr, "Selecting port: %s\n", "Did not bind port");
- exit(-1);
- }
- freeaddrinfo(result); //Get back that memory
- printf("debug: made it through set-up\n");
- if (listen(listen_fd, 10) == -1) {
- perror("listen");
- exit(-1);
- } //Check to make sure the listen worked
- printf("debug: listening on socket: %d\n", listen_fd);
- FD_SET(listen_fd, &all_fds); //add listen_fd to list
- max_fd = listen_fd; //keep track of the number of file descriptors
- printf("listen_fd on port: %d\n", listen_fd);
- chatLog_fd = open("chatlog.txt", O_CREAT|O_RDWR);
- while(1) {
- if (chat_count <= 10) {
- printf("debug: Waiting for new connection\n");
- addrlen = sizeof(remoteHost);
- if (new_fd = accept(listen_fd, (struct sockaddr*) &(remoteHost), &addrlen) != -1) {
- write(new_fd, "Welcome to the chat server!\n", 28);
- printf("debug: accepted new connection\n");
- if (new_fd > max_fd)
- max_fd = new_fd;
- if (value = pthread_create((chat+chat_count), NULL, chatDaemon, (void *) &new_fd) != 0) {
- fprintf(stderr, "Thread Creation: %s\n", gai_strerror(value));
- close(new_fd);
- free(chat+chat_count);
- chat_count--;
- }
- chat_count++;
- printf("New connection from %s on fd: %d\n", inet_ntop(remoteHost.ss_family, get_in_addr((struct sockaddr*) &remoteHost), remoteIP, INET6_ADDRSTRLEN), new_fd);
- }
- else {
- perror("accept");
- close(new_fd);
- }
- }
- else {
- addrlen = sizeof(remoteHost);
- if (new_fd = accept(listen_fd, (struct sockaddr*) &(remoteHost), &addrlen) != -1) {
- write(new_fd, "Chat server full -- disconnecting", 16);
- close(new_fd);
- }
- else {
- perror("accept");
- close(new_fd);
- }
- }
- } //END WHILE
- } //END MAIN
- void * chatDaemon(void * fd) {
- int my_fd = *((int *)fd);
- fd_set read_fds;
- int i, bytesRead;
- char *buffer;
- buffer = calloc(100, sizeof(char));
- grabMutex();
- FD_SET(my_fd, &all_fds);
- releaseMutex();
- for(;;) {
- if (bytesRead = recv(my_fd, buffer, 512, 0) <= 0) {
- if (bytesRead == 0) {
- printf("Socket %d disconnected\n", my_fd);
- }
- else {
- perror("recv");
- grabMutex();
- close(my_fd);
- FD_CLR(my_fd, &all_fds);
- releaseMutex();
- pthread_exit(NULL);
- }
- }
- if (select(max_fd + 1, &read_fds, NULL, NULL, NULL) == -1) {
- perror("select");
- exit(EXIT_FAILURE);
- }
- grabMutex();
- for (i = 0; i <= max_fd; i++) {
- if (FD_ISSET(i, &read_fds)) {
- if (send(i, buffer, bytesRead, 0) == -1) {
- perror("send");
- }
- }
- }
- write(chatLog_fd, buffer, bytesRead);
- releaseMutex();
- write(1, buffer, bytesRead);
- }
- }
- void *get_in_addr(struct sockaddr *sa) {
- if (sa->sa_family == AF_INET)
- return &(((struct sockaddr_in*)sa)->sin_addr);
- return &(((struct sockaddr_in6*)sa)->sin6_addr);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement