/* Net_select.c */
# Include <sys/types. h>
# Include <sys/socket. h>
# Include <stdio. h>
# Include <stdlib. h>
# Include <string. h>
# Include <sys/time. h>
# Include <sys/IOCTL. h>
# Include <unistd. h>
# Include <netinet/in. h>
# Include <malloc. h>
# Define Port 4321
# Define max_que_conn_nm 5
# Define max_sock_fd fd_setsize
# 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; // target user 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 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 );
}
Void sendlist_usr (puser_list P, int sockfd)
{
User_list end, Buff;
Int sendbytes;
End. user_fd = 6000;
// Send a message to the client
While (p-> next)
{
P = p-> next;
Memset (& buff, 0, sizeof (user_list ));
Buff. users_sockaddr = p-> users_sockaddr;
Buff. user_fd = p-> user_fd;
Buff. user_name = "W ";
If (sendbytes = Send (sockfd, & buff, sizeof (user_list), 0) =-1)
{
Perror ("send ");
Exit (1 );
}
}
If (sendbytes = Send (sockfd, & End, sizeof (user_list), 0) =-1) // indicates the end of the launch.
{
Perror ("send ");
Exit (1 );
}
}
Void manypeople_chat_fun (puser_list user, int FD, user_list buff)
{
Int sendbytes;
While (User-> next)
{
User = user-> next;
Printf ("% d \ n", user-> user_fd );
Strcpy (User-> Buf, Buff. BUF );
Strcpy (User-> Del, Buff. DEL );
If (User-> user_fd! = FD)
{
If (sendbytes = Send (User-> user_fd, user, sizeof (user_list), 0) =-1)
{
Perror ("send ");
Exit (1 );
}
}
}
}
Void singlepeople_chat_fun (INT target, user_list user)
{
Int sendbytes;
If (sendbytes = Send (target, & user, sizeof (user_list), 0) =-1)
{
Perror ("send ");
Exit (1 );
}
}
Int main ()
{
Puser_list user, Reuser;
Int sendbytes;
Struct sockaddr_in server_sockaddr, client_sockaddr;
Int sin_size, count;
Fd_set inset, tmp_inset;
Int sockfd, client_fd, FD;
U_long hbuff;
Char bufsym [5];
User = craet_user_listhead (); // create a user list file header
Reuser = user;
User_list Buff;
If (sockfd = socket (af_inet, sock_stream, 0) =-1) // create a socket
{
Perror ("socket ");
Exit (1 );
}
Server_sockaddr.sin_family = af_inet;
Server_sockaddr.sin_port = htons (port );
Server_sockaddr.sin_addr.s_addr = inaddr_any;
Bzero (& (server_sockaddr.sin_zero), 8 );
Int I = 1;/* bind the local address to the socket repeatedly */
Setsockopt (sockfd, sol_socket, so_reuseaddr, & I, sizeof (I ));
If (BIND (sockfd, (struct sockaddr *) & server_sockaddr, sizeof (struct sockaddr) =-1)
{
Perror ("bind ");
Exit (1 );
}
Printf ("% s \ n", (char *) inet_ntoa (& server_sockaddr.sin_addr ));
If (Listen (sockfd, max_que_conn_nm) =-1)
{
Perror ("listen ");
Exit (1 );
}
Printf ("listening... \ n ");
/* Use the descriptor of the socket function as the file descriptor */
Fd_zero (& inset); // initialize the socket set
Fd_set (sockfd, & inset); // The select () mechanism provides an fd_set data structure, which is actually a long array?
// Each array element can be associated with an open file handle (whether it is a socket handle, another file, named pipe, or device handle ).
While (1)
{
Tmp_inset = inset;
Sin_size = sizeof (struct sockaddr_in );
Memset (& buff, 0, sizeof (user_list ));
/* Call the select function */
Printf ("Select... \ n ");
If (! (Select (max_sock_fd, & tmp_inset, null)> 0 ))
{
Perror ("select ");
Close (sockfd );
Exit (1 );
}
For (FD = 0; FD <max_sock_fd; FD ++)
{
If (fd_isset (FD, & tmp_inset)> 0)
{
If (FD = sockfd)
{/* The server receives client connection requests */
If (client_fd = accept (sockfd, (struct sockaddr *) & client_sockaddr, & sin_size) =-1)
{
Perror ("accept ");
Exit (1 );
}
Fd_set (client_fd, & inset );
Strcpy (buff. Del, "INL"); // set the user's online flag
Manypeople_chat_fun (user, FD, buff); // enter the group chat mode to send online information to online users.
Strcpy (buff. Del, "onl ");
Insert_userlist (user, client_sockaddr, client_fd, "W"); // insert login user information
Printf ("% d \ n", user-> user_fd );
Sendlist_usr (user, client_fd); // send the online user to the client.
// Printf ("Client IP: % s \ n", (char *) inet_ntoa (client_sockaddr.sin_addr ));
}
Else/* process messages sent from the client */
{
If (COUNT = Recv (FD, & buff, sizeof (user_list), 0)> 0)
{
Strncpy (bufsym, Buff. Buf, 4 );
If (strcmp (bufsym, "sinp") = 0) // if you select private chat
{
Singlepeople_chat_fun (buff. rece_id, buff );
}
If (strcmp (bufsym, "manp") = 0) // if you select public chat
{
User = Reuser;
Manypeople_chat_fun (user, FD, buff );
}
}
Else
{
Close (FD );
Fd_clr (FD, & inset );
Delet_list (user, FD); // deletes the offline user list.
Strcpy (buff. Del, "Del ");
Buff. rece_id = FD;
Manypeople_chat_fun (user, FD, buff); // send a user exit signal to the client
Strcpy (buff. Del, "onl ");
Printf ("client % d (socket) has left \ n", FD );
}
}
}/* End of if fd_isset */
}/* End of for FD */
}/* End if while */
Close (sockfd );
Exit (0 );
}