/* demo/tcp.c - 21/09/2000 - Edouard.Thiel@lif.univ-mrs.fr */ #include He_node *princ, *panel, *text1, *butt1, *text2, *text3, *rule1, *b_quit; int princ_width, princ_height; #define CLIENTMAX 3 typedef struct { He_node *mess, *text_recv, *text_send, *butt_send, *butt_stop; int fd; } Client_struct; Client_struct client_tab[CLIENTMAX]; int port_server = -1, port_host = -1, sock_ecoute = -1; struct sockaddr_in adr_ecoute; /* Prototypes */ int client_find (int fd); void client_add (int fd, int ind, struct sockaddr_in *adr); void client_remove (int fd); void ecoute_io_proc (int fd, Ulong rcond, void *data); void client_io_proc (int fd, Ulong rcond, void *data); void sig1_proc (int sig, void *data); void quit_proc (He_node *hn); void start_server_proc (He_node *hn); void stop_server_proc (He_node *hn); void connect_to_host_proc (He_node *hn); void disconnect_from_host_proc (He_node *hn); void send_message_to_host_proc (He_node *hn); void boite_erreur (char *txt1, char *txt2); void princ_resize_proc (He_node *hn, int width, int height); int main (int argc, char *argv[]); /*---------------------- T A B L E A U C L I E N T S ----------------------*/ int client_find (int fd) { int i; for (i = 0; i < CLIENTMAX; i++) if (client_tab[i].fd == fd) return i; return -1; } void client_add (int fd, int ind, struct sockaddr_in *adr) { struct hostent *hp; char bla[256]; client_tab[ind].fd = fd; hp = gethostbyaddr ( (char*) &adr->sin_addr, sizeof(adr->sin_addr), AF_INET); sprintf (bla, "(%d) %s:%d", fd, hp ? hp->h_name : "unknown", ntohs(adr->sin_port) ); HeSetMessageLabel (client_tab[ind].mess, bla); HeSetTextValue (client_tab[ind].text_recv, ""); HeAddIO (fd, HE_IO_READ, client_io_proc, NULL); } void client_remove (int fd) { int ind = client_find (fd); if (ind < 0) return; close (fd); HeRemoveIO (fd); client_tab[ind].fd = -1; HeSetMessageLabel (client_tab[ind].mess, "no connection"); } /*---------------------- E N T R E E S / S O R T I E S ----------------------*/ void ecoute_io_proc (int fd, Ulong rcond, void *data) { int sock_servi, ind; socklen_t longueur; struct sockaddr_in adr_servi; longueur = sizeof(struct sockaddr_in); memcpy (&adr_servi, &adr_ecoute, longueur); /* Test cx pendante */ sock_servi = accept (sock_ecoute, (struct sockaddr *) &adr_servi, &longueur); if (sock_servi < 0) return; /* pas de cx pendante */ ind = client_find(-1); /* cherche une entrée libre */ if (ind < 0) { boite_erreur ("To many connections", ""); close (sock_servi); return; } client_add (sock_servi, ind, &adr_servi); } void client_io_proc (int fd, Ulong rcond, void *data) { char buf[4096]; int n, ind; /* On lit sur fd pour éviter de se faire rappeler indéfiniment en cas d'erreur. */ n = read (fd, buf, 4096); ind = client_find (fd); if (ind < 0) { HeError("client_io_proc: fd non trouve"); return; } if (n < 0) { perror("client_io_proc: read"); return; } if (n == 0) { /* Fin de connexion */ client_remove (fd); return; } buf[n] = 0; /* 0 terminal */ HeSetTextValue (client_tab[ind].text_recv, buf); } /*------------------------------ S I G N A U X ------------------------------*/ void sig1_proc (int sig, void *data) { HeQuit(0); } /*---------------------------- C A L L B A C K S ----------------------------*/ void quit_proc (He_node *hn) { HeQuit(0); } void start_server_proc (He_node *hn) { port_server = atoi(HeGetTextValue(text1)); if ((sock_ecoute = HeCreateSocket (SOCK_STREAM, &port_server, &adr_ecoute)) >= 0) { char bla[100]; sprintf(bla, "%d", port_server); HeSetTextValue (text1, bla); } else { boite_erreur ("Bad port number", "type 0 for auto"); return; } if (listen (sock_ecoute, SOMAXCONN) < 0) { boite_erreur ("listen", strerror(errno)); return; } if (HeAddIO (sock_ecoute, HE_IO_READ, ecoute_io_proc, NULL) < 0) port_server = -1; else { HeSetTextNotifyProc (text1, NULL); HeSetButtonLabel(butt1, "Stop"); HeSetButtonNotifyProc (butt1, stop_server_proc); } } void stop_server_proc (He_node *hn) { if (sock_ecoute < 0) return; close (sock_ecoute); HeRemoveIO (sock_ecoute); sock_ecoute = -1; HeSetTextValue (text1, "0"); HeSetTextNotifyProc (text1, start_server_proc); HeSetButtonLabel(butt1, "Start"); HeSetButtonNotifyProc (butt1, start_server_proc); } void connect_to_host_proc (He_node *hn) { char *nom_host = HeGetTextValue (text2); int port_host = atoi(HeGetTextValue (text3)); struct sockaddr_in adr_host, adr_local; int sock_client, port_local = 0, ind; struct hostent *hp; ind = client_find(-1); /* cherche une entrée libre */ if (ind < 0) { boite_erreur ("To many connections", ""); return; } /* Creation socket locale */ sock_client = HeCreateSocket (SOCK_STREAM, &port_local, &adr_local); if (sock_client < 0) { boite_erreur ("Erreur création socket locale", ""); return; } /* Preparation de l'adresse distante */ memset ((char *) &adr_host, 0, sizeof(struct sockaddr_in)); adr_host.sin_family = AF_INET; adr_host.sin_port = htons (port_host); /* Recherche de l'adresse internet de la machine distante */ if ((hp = gethostbyname (nom_host)) == NULL) { boite_erreur ("Host inconnu:", nom_host); return; } memcpy (&adr_host.sin_addr.s_addr, hp->h_addr, hp->h_length); /* Demande de connection blocante */ if (connect (sock_client, (struct sockaddr *) &adr_host, sizeof(struct sockaddr_in)) < 0) { boite_erreur ("connect:", strerror(errno)); return; } client_add (sock_client, ind, &adr_host); } void disconnect_from_host_proc (He_node *hn) { Client_struct *servi = HeGetClientData(hn); if (servi->fd < 0) return; client_remove (servi->fd); } void send_message_to_host_proc (He_node *hn) { Client_struct *servi = HeGetClientData(hn); if (servi->fd < 0) return; write (servi->fd, HeGetTextValue(servi->text_send), HeGetTextLen(servi->text_send) ); } /*---------------------------- I N T E R F A C E ----------------------------*/ void boite_erreur (char *txt1, char *txt2) { HeSimpleDialog ( HE_DIALOG_BELL, HE_DIALOG_TITLE, "WARNING", HE_DIALOG_MESSAGE, txt1, HE_DIALOG_MESSAGE, txt2, HE_DIALOG_BUTTOK, "Ok", 0); } void princ_resize_proc (He_node *hn, int width, int height) { int i; HeSetHeight (princ, princ_height); if (width < princ_width) HeSetWidth (princ, princ_width); HeExpand (panel, NULL, HE_BOTTOM_RIGHT); HeJustify (b_quit, NULL, HE_RIGHT); HeSetWidth(rule1, HeGetWidth(panel)/2); HeSetX(rule1, HeGetWidth(panel)/4); for (i = 0; i < CLIENTMAX; i++) { HeJustify (client_tab[i].butt_send, NULL, HE_RIGHT); HeJustify (client_tab[i].butt_stop, NULL, HE_RIGHT); HeExpand (client_tab[i].text_send, client_tab[i].butt_send, HE_RIGHT); HeExpand (client_tab[i].text_recv, client_tab[i].butt_stop, HE_RIGHT); } } /*--------------------------------- M A I N ---------------------------------*/ int main (int argc, char *argv[]) { int i; char bla[256]; HeInit (&argc, &argv); princ = HeCreateFrame (); HeSetFrameLabel (princ, "Client/server tcp"); HeSetFrameResizeProc (princ, princ_resize_proc); panel = HeCreatePanel (princ); HeCreateMessageP (panel, "Server:", TRUE); if (gethostname(bla, sizeof(bla)) < 0) sprintf (bla, "localhost"); HeCreateMessageP (panel, bla, FALSE); HeCreateMessageP (panel, "port:", TRUE); text1 = HeCreateText (panel); HeSetTextVisibleLen (text1, 6); HeSetTextValue (text1, "0"); HeSetTextNotifyProc (text1, start_server_proc); HeSetTip (text1, "Mettez 0 pour qu'un numéro\n" "de port disponible soit\n" "automatiquement attribué."); butt1 = HeCreateButtonP (panel, "Start", start_server_proc, NULL); HeSetTip (butt1, "Démarre le serveur TCP"); HeSetAutoFit (butt1, FALSE); b_quit = HeCreateButtonP (panel, "Quit", quit_proc, NULL); HeSetPanelLayout (panel, HE_LINE_FEED); HeCreateMessageP (panel, "Host:", TRUE); text2 = HeCreateText (panel); HeSetTextVisibleLen (text2, 20); HeSetTextValue (text2, bla); HeCreateMessageP (panel, "port:", TRUE); text3 = HeCreateText (panel); HeSetTextVisibleLen (text3, 6); HeSetTextNotifyProc (text3, connect_to_host_proc); HeCreateButtonP (panel, "Connect", connect_to_host_proc, NULL); HeSetPanelLayout (panel, HE_LINE_FEED); rule1 = HeCreateRule (panel); HeSetPanelLayout (panel, HE_LINE_FEED); for (i = 0; i < CLIENTMAX; i++) { client_tab[i].fd = -1; HeCreateMessageP (panel, "Stat:", TRUE); client_tab[i].mess = HeCreateMessageP (panel, "no connection", FALSE); HeSetPanelLayout (panel, HE_LINE_FEED); HeCreateMessageP (panel, "Send:", TRUE); client_tab[i].text_send = HeCreateText (panel); HeSetTextVisibleLen (client_tab[i].text_send, 40); HeSetTextNotifyProc (client_tab[i].text_send, send_message_to_host_proc); HeSetClientData (client_tab[i].text_send, &client_tab[i]); client_tab[i].butt_send = HeCreateButtonP (panel, "Send", send_message_to_host_proc, &client_tab[i]); HeSetPanelLayout (panel, HE_LINE_FEED); HeCreateMessageP (panel, "Recv:", TRUE); client_tab[i].text_recv = HeCreateText (panel); HeSetTextVisibleLen (client_tab[i].text_recv, 40); client_tab[i].butt_stop = HeCreateButtonP (panel, "Stop", disconnect_from_host_proc, &client_tab[i]); HeSetPanelLayout (panel, HE_LINE_FEED); } HeFit(panel); HeFit(princ); princ_width = HeGetWidth(princ); princ_height = HeGetHeight(princ); HeAddSignal (SIGHUP, sig1_proc, NULL); HeAddSignal (SIGTERM, sig1_proc, NULL); HeAddSignal (SIGINT, sig1_proc, NULL); HeAddSignal (SIGQUIT, sig1_proc, NULL); HeMainLoop (princ); /* Fermeture sockets serveur et clients */ if (sock_ecoute >= 0) close(sock_ecoute); for (i = 0; i < CLIENTMAX; i++) if (client_tab[i].fd >= 0) close(client_tab[i].fd); return he_exit_code; }