/* Client. C */
# Include <sys/types. h>
# Include <sys/socket. h>
# Include <stdio. h>
# Include <stdlib. h>
# Include <string. h>
# Include <sys/IOCTL. h>
# Include <unistd. h>
# Include <netdb. h>
# Include <netinet/in. h>
# Include <malloc. h>
// # Include <curses. h> // Linux graphical programming interface function
# Define Port 4321
# Define buffer_size 1024
Typedef struct user
{
Struct sockaddr_in users_sockaddr; // user IP Address
Int user_fd; // user connection socket
Char * user_name; // user alias
Char Buf [buffer_size]; // user message
Char del [4]; // Delete the offline user signal flag
Int rece_id;
Struct user * next;
} User_list, * puser_list;
Puser_list craet_user_listhead ()
{
Puser_list phead = (puser_list) malloc (sizeof (user_list ));
If (phead = NULL)
{
Printf ("the dynamic memory allocation is fail \ n ");
Exit (-1 );
}
Phead-> next = NULL;
Return phead;
}
Puser_list craet_user_buff ()
{
Puser_list pbuff = (puser_list) malloc (sizeof (user_list ));
If (pbuff = NULL)
{
Printf ("the dynamic memory allocation is fail \ n ");
Exit (-1 );
}
Return pbuff;
}
Puser_list insert_userlist (puser_list P, struct sockaddr_in uaddr, int FD, char * name)
{
Int I = 0;
Puser_list pnew = (puser_list) malloc (sizeof (user_list ));
If (pnew = NULL)
{
Printf ("the dynamic memory allocation is fail \ n ");
Exit (-1 );
}
Pnew-> users_sockaddr = uaddr;
Pnew-> user_fd = FD;
While (p-> next)
{
P = p-> next;
}
P-> next = pnew;
Pnew-> next = NULL;
Return;
}
Void delet_list (puser_list P, int FD)
{
Puser_list Q;
Do
{
Q = P; // Save the previous address first
P = p-> next;
If (p-> user_fd = FD)
{
Q-> next = p-> next;
Free (P );
}
} While (p-> next );
}
Char * choosechatmode (INT sockfd, char * C)
{Int sendbytes, FD;
Printf ("Please choose the specified people chat? Or single people chat \ n ");
Printf ("messaging people chat please input manp \ n ");
Printf ("single people chat please input sinp \ n ");
Scanf ("% s", C );
While (strcmp ("sinp", c )! = 0) & (strcmp ("manp", c )! = 0 ))
{
Printf ("Please input the correct command !! \ N ");
Scanf ("% s", C );
}
Return C;
}
Void show_online_users_list (puser_list user)
{
Printf ("the online user list: -------------------------------- \ n ");
Do
{
User = user-> next;
Printf ("User socket is % d:", user-> user_fd );
Printf ("the user IP: % s \ n", (char *) inet_ntoa (User-> users_sockaddr.sin_addr ));
} While (User-> next );
Printf ("************************************* * **************** \ n ");
}
Int chack_socket_number (puser_list user, int FD)
{
While (User-> next)
{
If (User-> user_fd = FD) return 0; // This user is included in the online user list.
User = user-> next;
}
Printf ("the socket number in the online_user list is not exit !!! \ N ");
Return 1;
}
Int main (INT argc, char * argv [])
{
Puser_list user, zero;
User_list Buff;
User_list rebuff;
Int recvbytes;
Int sockfd, sendbytes;
Struct hostent * Host;
Struct sockaddr_in serv_addr;
Char C [10];
User = craet_user_listhead (); // create a user list file? Zero = user;
Zero = user;
Pid_t child;
Int FD;
/* Address resolution function */
If (host = gethostbyname (argv [1]) = NULL)
{
Perror ("gethostbyname ");
Exit (1 );
}
/* Create a socket */
If (sockfd = socket (af_inet, sock_stream, 0) =-1)
{
Perror ("socket ");
Exit (1 );
}
/* Set parameters in the sockaddr_in struct */
Serv_addr.sin_family = af_inet;
Serv_addr.sin_port = htons (port );
Serv_addr.sin_addr = * (struct in_addr *) Host-> h_addr );
Bzero (& (serv_addr.sin_zero), 8 );
/* Call the connect function to actively initiate a connection to the server */
If (connect (sockfd, (struct sockaddr *) & serv_addr, sizeof (struct sockaddr) =-1)
{
Perror ("Connect ");
Exit (1 );
}
// Receives a list of online users.
While (1)
{
Memset (& buff, 0, sizeof (user_list ));
If (recvbytes = Recv (sockfd, & buff, sizeof (user_list), 0) <0)
{
Perror ("Recv ");
}
Insert_userlist (user, Buff. users_sockaddr, Buff. user_fd, "R ");
If (buff. user_fd = 6000) break; // if this flag is received, the receipt is complete.
}
Show_online_users_list (User); // displays the online user list
Choosechatmode (sockfd, c); // select the group chat mode or private chat Mode
/* Send a message to the server */
Memset (& buff, 0, sizeof (user_list ));
If (strcmp (C, "sinp") = 0) // if you select single chat Mode
{
Do
{
Printf ("Please input the user liner number !! \ N ");
Scanf ("% d", & FD );
Buff. rece_id = FD; // Save the selected target ID.
} While (chack_socket_number (user, FD); // check whether the target ID is in the online user list
}
Strcpy (buff. Buf, c); // Add the flag of the chat mode to the array Header
Printf ("you can chat now! \ N ");
/* Create a sub-process */
If (child = fork () =-1)
{
Printf ("fork error \ n ");
Exit (1 );
}
While (1)
{
If (child = 0) // sub-process
{
Scanf ("% s", Buff. BUF + 4 );
If (strncmp ("sinp", Buff. BUF + 4, 4) = 0) // If you switch to private chat Mode
{
Show_online_users_list (User); // displays the online user list
Do
{
Printf ("Please input the user liner number !! \ N ");
Scanf ("% d", & FD );
Buff. rece_id = FD; // Save the selected target ID.
} While (chack_socket_number (user, FD); // check whether the target ID is in the online user list
Strcpy (buff. Buf, "sinp"); // Add the flag of the chat mode selection to the array Header
}
Else if (strncmp ("manp", Buff. BUF + 4, 4) = 0)
{
Strcpy (buff. Buf, "manp"); // Add the flag of the chat mode selection to the array Header
}
If (sendbytes = Send (sockfd, & buff, sizeof (user_list), 0) =-1)
{
Perror ("send ");
Exit (1 );
}
}
Else if (Child> 0) // parent process
{
Memset (& rebuff, 0, sizeof (user_list ));
If (Recv (sockfd, & rebuff, sizeof (user_list), 0)> 0)
{
If (strcmp (rebuff. Del, "Del") = 0) // determine if someone is offline
{
Printf ("\ 33 [33m \ 33 [1 m ");
Printf ("the % d is outline !! \ N ", rebuff. user_fd );
Printf ("\ 33 [0 m \ n ");
Delet_list (user, rebuff. user_fd); // Delete the offline user from the user list
}
If (strcmp (rebuff. Del, "INL") = 0) // determine if someone is online
{
Printf ("\ 33 [33m \ 33 [1 m ");
Printf ("the % d is inline !! \ N ", rebuff. user_fd );
Printf ("\ 33 [0 m \ n ");
Insert_userlist (user, rebuff. users_sockaddr, rebuff. user_fd, "W"); // append a new online user to the list
}
Else
{
Printf ("\ 33 [33m \ 33 [1 m ");
Printf ("received % d: % s \ n", rebuff. rece_id, rebuff. BUF + 4 );
Printf ("\ 33 [0 m \ n ");
}
}
}
}
Close (sockfd );
Exit (0 );
}