Small Linux C Project - Chat Room




multi-threaded chat room

Service-Terminal:

Realize multi-user group chat function (the upper limit of the number of people can be set);

Messages sent by each user can be received by other users connected to the server;

The user enters "bye" to exit, and the server enters " quit " to exit.

 

There are three functions on the server

Main function main : server-side initialization, accepting connections;

Message processing function rcv_snd : Receive a message from a user, and send it to all other users after simple processing;

Exit function quit : When quit is entered , the server program terminates.

These three functions belong to three threads (to be precise, more than or equal to three). The Main function acts as the main thread and creates a thread where the exit function is located, and a thread that processes messages for this connection every time a new user is connected.

 

Client:

Establish a connection to the server, send and receive messages

 

The client has a total of two functions

Main function main : Initialize the client socket, establish a connection with the server, receive messages and display them locally

Send function snd : read the message from the console and send it to the server

These two functions run on two threads, one is the thread where the main function is located, and the other is the thread where the sending function created by the main function is located.

 

 

Attached:

Macro definition debug print switch

#define DEBUG_PRINT 1

#ifdef DEBUG_PRINT

#define DEBUG(format, ...) printf(“FILE: “__FILE__”, LINE: %d: “format”\n”, __LINE__, ##__VA_ARGS__)

#else

#define DEBUG(format, ...)

#endif

 

-lpthread is required when creating a thread when gcc compiles

Phtread_t thread;  Pthread_creat(&thread, NULL, (void *)quit, NULL);

Pthread_creat(malloc(sizeof(pthread_t)), NULL, (void *)rcv_snd, (void *)i);

 

System time #include <time.h>

Time_t ticks = time(NULL); printf(“%s\n”, ctime(&ticks));

 

Server

Struct sockaddr_in serv_addr;

Bzero(&serv_addr, sizeof(serv_addr));

Serv_addr.sin_family = AF_INET;

Serv_addr.sin_port = htons(PORT);

Serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

 

Listenfd = socket (AF_INET, SOCK_STREAM, 0);

Bind(listenfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));

Listen(listenfd, 10);

Int len = sizeof(cli_addr);

Connfd[i] = accept(listenfd, (struct sockaddr *)&cli_addr, &len);

 

client

Struct sockaddr_in serv_addr;

Bzero(&serv_addr, sizeof(serv_addr));

Serv_addr.sin_family = AF_INET;

Serv_addr.sin_port = htons(PORT);

Inet_pton(IP, &serv_addr.sin_addr);

 

Sockfd = socket (AF_INET, SOCK_STREAM, 0);

Connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));

 source code server.c

  1 #include <stdio.h>
  2 #include <stdlib.h>     // exit
  3 #include <string.h>
  4 #include <unistd.h>     // bind listen
  5 #include <time.h>       // time(NULL)   ctime(&ticks)
  6 #include <netinet/in.h>
  7 #include <arpa/inet.h> // must be included for inet_ntop
  8
  9 #define PORT 8000
 10 #define MAXMEM 10
 11 #define BUFFSIZE 128
 12
 13 //#define DEBUG_PRINT 1 // Macro definition debug switch
 14 #ifdef DEBUG_PRINT
 15 #define DEBUG(format, ...) printf("FILE: "__FILE__", LINE: %d: "format"\n", __LINE__, ##__VA_ARGS__)
 16 #else
 17 #define DEBUG(format, ...)
 18 #endif
 19
 20 int listenfd, connfd[MAXMEM];
 21
 22 void quit();
 23 void rcv_snd(int p);
 24
 25 int main()
 26 {
 27         struct sockaddr_in serv_addr, cli_addr;
 28 //      int len = sizeof(cli_addr), i;
 29         int i;
 30         time_t ticks;
 31         pthread_t thread;
 32         char buff[BUFFSIZE];
 33
 34         printf("running...\n(Prompt: enter command ""quit"" to exit server)\n");
 35 DEBUG("=== initialize..."); // Initialize and fill the server address structure
 36         bzero(&serv_addr, sizeof(struct sockaddr_in));
 37 serv_addr.sin_family = AF_INET;
 38         serv_addr.sin_port = htons(PORT);
 39         serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
 40
 41 DEBUG("=== socket..."); // socket creates a listening socket on the server side
 42 listenfd = socket (AF_INET, SOCK_STREAM, 0);
 43         if(listenfd < 0)
 44         {
 45                 perror("fail to socket");
 46                 exit(-1);
 47         }
 48
 49 DEBUG("=== bind..."); // bind binds the socket to the populated address structure
 50         if(bind(listenfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
 51         {
 52                 perror("fail to bind");
 53                 exit(-2);
 54         }
 55
 56 DEBUG("=== listening..."); // listen turns an actively connected socket into a passive listening socket
 57         listen(listenfd, MAXMEM);
 58
 59 /* === Create a thread, manage the server program, and call the quit function === */
 60         pthread_create(&thread, NULL, (void *)(quit), NULL);
 61
 62 // Initialize the socket descriptor array to -1, indicating idle
 63         for(i=0; i<MAXMEM; i++)
 64                 connfd[i] = -1;
 65
 66         while(1)
 67         {
 68                 int len;// = sizeof(cli_addr);
 69                 for(i=0; i<MAXMEM; i++)
 70                 {
 71                         if(connfd[i] == -1)
 72                                 break;
 73                 }
 74 // accept gets a connection from the connection queue accepted by listen
 75                 connfd[i] = accept(listenfd, (struct sockaddr *)&cli_addr, &len);
 76                 if(connfd[i] < 0)
 77                 {
 78                         perror("fail to accept");
 79 // continue; // This sentence can be omitted, accept will block and wait
 80                 }
 81                 ticks = time(NULL);
 82                 //sprintf(buff, "%.24s\r\n", ctime(&ticks));
 83                 printf("%.24s\n\tconnect from: %s, port %d\n",
 84                                 ctime(&ticks), inet_ntop(AF_INET, &(cli_addr.sin_addr), buff, BUFFSIZE),
 85 ntohs(cli_addr.sin_port)); // Note the use of inet_ntop, #include <arpa/inet.h>
 86
 87 /* === Create a thread for the current socket and process messages from the current socket === */
 88                 pthread_create(malloc(sizeof(pthread_t)), NULL, (void *)(&rcv_snd), (void *)i);
 89         }
 90         return 0;
 91 }
 92
 93 void quit()
 94 {
 95         char msg[10];
 96         while(1)
 97         {
 98 scanf("%s", msg); // scanf, unlike fgets, does not read the last newline entered
 99                 if(strcmp(msg, "quit") == 0)
100                 {
101                         printf("Byebye... \n");
102                         close(listenfd);
103                         exit(0);
104                 }
105         }
106 }
107
108 void rcv_snd(int n)
109 {
110 int len, i;
111         char name[32], mytime[32], buf[BUFFSIZE];
112         time_t ticks;
113 int ret;
114
115 // Get the name of the socket user corresponding to this thread
116         write(connfd[n], "your name: ", strlen("your name: "));
117         len = read(connfd[n], name, 32);
118         if(len > 0)
119 name[len-1] = '\0'; // strip newline
120         strcpy(buf, name);
121         strcat(buf, "\tjoin in\n\0");
122 // Tell all users that the current user has joined
123         for(i=0; i<MAXMEM; i++)
124         {
125                 if(connfd[i] != -1)
126                         write(connfd[i], buf, strlen(buf));
127         }
128
129         while(1)
130         {
131                 char temp[BUFFSIZE];
132                 if((len=read(connfd[n], temp, BUFFSIZE)) > 0)
133                 {
134                         temp[len-1] = '\0';
135 // When the user enters bye, the current user exits
136                         if(strcmp(temp, "bye") == 0)
137                         {
138                                 close(connfd[n]);
139                                 connfd[n] = -1;
140                                 pthread_exit(&ret);
141                         }
142                         ticks = time(NULL);
143                         sprintf(mytime, "%.24s\r\n", ctime(&ticks));
144                         //write(connfd[n], mytime, strlen(mytime));
145                         strcpy(buf, name);
146                         strcat(buf, "\t");
147                         strcat(buf, mytime);
148                         strcat(buf, "\r\t");
149                         strcat(buf, temp);
150                         strcat(buf, "\n");
151
152                         for(i=0; i<MAXMEM; i++)
153                         {
154                                 if(connfd[i] != -1)
155                                         write(connfd[i], buf, strlen(buf));
156                         }
157                 }
158         }
159
160 }
source code client.c

  1 /*
  2  * FILE: client.c
  3  * DATE: 20180206
  4  * ==============
  5  */
  6
  7 #include <stdio.h>
  8 #include <stdlib.h>
  9 #include <string.h>
 10
 11 #include <netinet/in.h>
 12
 13 #define BUFFSIZE 128
 14 #define HOST_IP "192.168.159.3"
 15 #define PORT 8000
 16
 17 int sockfd;
 18
 19 void snd();
 20
 21 int main()
 22 {
 23 pthread_t thread; // pthread_t thread, add -lpthread when gcc compiles
 24         struct sockaddr_in serv_addr;   // struct sockaddr_in
 25         char buf[BUFFSIZE];
 26 // Initialize the server address structure
 27         bzero(&serv_addr, sizeof(struct sockaddr_in));  // bzero 清零
 28 serv_addr.sin_family = AF_INET; // sin_family AF_INET
 29         serv_addr.sin_port = htons(PORT);       // sin_port     htons(PORT)
 30         inet_pton(HOST_IP, &serv_addr.sin_addr);        // inet_pton
 31 // Create client socket
 32 sockfd = socket(AF_INET, SOCK_STREAM, 0); // socket creates a socket
 33         if(sockfd < 0)
 34         {
 35                 perror("fail to socket");
 36                 exit(-1);
 37         }
 38 // Establish a connection with the server
 39         printf("connecting... \n");
 40         if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) // connect
 41         {
 42                 perror("fail to connect");
 43                 exit(-2);
 44         }
 45 /* === The program is divided into two threads from here === */
 46 // Create a thread that sends a message and call the function snd that sends a message
 47         pthread_create(&thread, NULL, (void *)(&snd), NULL);    // pthread_create
 48 // Thread receiving message
 49         while(1)
 50         {
 51 int len;
 52 if((len=read(sockfd, buf, BUFFSIZE)) > 0) // read reads the communication socket
 53                 {
 54 buf[len] = '\0'; // Add a terminator to avoid displaying the content left in the buffer
 55                         printf("\n%s", buf);
 56 fflush(stdout); // fflush flushes standard output to ensure timely display of content
 57                 }
 58         }
 59         return 0;
 60 }
 61
 62 // function to send message
 63 void snd()
 64 {
 65         char name[32], buf[BUFFSIZE];
 66
 67 fgets(name, 32, stdin); // fgets will read the newline after the input string
 68 write(sockfd, name, strlen(name)); // write writes to the communication socket
 69         while(1)
 70         {
 71                 fgets(buf, BUFFSIZE, stdin);
 72                 write(sockfd, buf, strlen(buf));
 73 if(strcmp(buf, "bye\n") == 0) // Note the \n here
 74                         exit(0);
 75         }
 76 }


 


Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326700264&siteId=291194637