/** * @file server.c * * * @brief Julius サーバと通信を行うための低レベル関数群 * * * * @brief Low-level functions for send/receive data to/from Julius server * * * @author Akinobu LEE * @date Thu Mar 24 12:07:24 2005 * * $Revision: 1.4 $ * */ /* * Copyright (c) 2002-2012 Kawahara Lab., Kyoto University * Copyright (c) 2002-2005 Shikano Lab., Nara Institute of Science and Technology * Copyright (c) 2005-2012 Julius project team, Nagoya Institute of Technology * All rights reserved */ #include "japi.h" #ifdef WINSOCK int winsock_initialized = 0; ///< 1 of winsock has been initialized #endif /** * * Juliusサーバへの接続を行う. * * @param hostname [in] 接続先のホスト名 * @param portnum [in] 接続するポート番号 * * @return ソケットデスクリプタ * * * Establish a connection to Julius server. * * @param hostname [in] host name to connect * @param portnum [in] port number to connect * * @return the socket descriptor * */ int do_connect(char *hostname, int portnum) { static struct hostent *hp; static struct sockaddr_in sin; int sd; #ifdef WINSOCK /* if not initialized yet, initialize winsock here */ if (winsock_initialized == 0) { WSADATA data; WSAStartup(0x1010, &data); winsock_initialized = 1; } #endif /* get host entry */ if ((hp = gethostbyname(hostname)) == NULL) { fprintf(stderr, "Error: host \"%s\" not found\n", hostname); exit(1); } #ifdef WINSOCK if((sd = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET){ perror("Error: socket()") ; printf("Error code: %d\n", WSAGetLastError()); switch(WSAGetLastError()) { case WSANOTINITIALISED: printf("A successful WSAStartup must occur before using this function.\n"); break; case WSAENETDOWN: printf("The network subsystem or the associated service provider has failed.\n"); break; case WSAEAFNOSUPPORT: printf("The specified address family is not supported. \n"); break; case WSAEINPROGRESS: printf("A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function. \n"); break; case WSAEMFILE: printf("No more socket descriptors are available. \n"); break; case WSAENOBUFS: printf("No buffer space is available. The socket cannot be created. \n"); break; case WSAEPROTONOSUPPORT: printf("The specified protocol is not supported. \n"); break; case WSAEPROTOTYPE: printf("The specified protocol is the wrong type for this socket. \n"); break; case WSAESOCKTNOSUPPORT: printf("The specified socket type is not supported in this address family. \n"); break; } exit(1); } #else /* ~WINSOCK */ /* create socket */ if((sd = socket(PF_INET, SOCK_STREAM, 0)) < 0){ perror("Error: socket()") ; exit(1); } #endif /* ~WINSOCK */ /* connect */ memset((char *)&sin, 0, sizeof(sin)); memcpy(&sin.sin_addr, hp->h_addr, hp->h_length); sin.sin_family = hp->h_addrtype; sin.sin_port = htons(portnum); fprintf(stderr, "connecting to %s:%d...", hostname, portnum); if (connect(sd, (struct sockaddr *)&sin, sizeof(sin)) < 0) { perror("Error"); exit(1); } fprintf(stderr, "done\n"); return(sd); } /** * * 接続を切断する. * * @param sd [in] 送信ソケット * * * Disconnect the server. * * @param sd [in] socket descriptor * */ void do_disconnect(int sd) { #ifdef WINSOCK closesocket(sd); #else if (close(sd) < 0) { fprintf(stderr,"Error: close() failed"); } #endif } /** * * サーバーに文字列を送信する汎用関数(printf 形式) * * @param sd [in] 送信ソケット * @param fmt [in] フォーマット * @param ... [in] フォーマットに対する引数 * * * General function to send string to server (printf style). * * @param sd [in] socket to send data * @param fmt [in] format * @param ... [in] arguments to the format * */ void do_sendf(int sd, char *fmt, ...) { static char buf[MAXLINELEN]; va_list ap; int n; va_start(ap, fmt); vsnprintf(buf, MAXLINELEN, fmt, ap); #ifdef WINSOCK n = send(sd, buf, strlen(buf), 0); #else n = write(sd, buf, strlen(buf)); #endif if (n < 0) { perror("Error: do_sendf"); } va_end(ap); } /** * * サーバにバッファの内容を送信する. * * @param sd [in] 送信ソケット * @param buf [in] 送信内容の文字列 * * * Send content of the buffer to server. * * @param sd [in] socket to send data * @param buf [in] string to send * */ void do_send(int sd, char *buf) { int n; #ifdef WINSOCK n = send(sd, buf, strlen(buf), 0); #else n = write(sd, buf, strlen(buf)); #endif if (n < 0) { perror("Error: do_send"); } } /** * * サーバーからメッセージを一行読み込みバッファに格納する. * 末尾の改行コードは削除される. * * @param sd [in] 受信ソケット * @param buf [out] 受信したメッセージを格納するバッファ * @param maxlen [in] @a buf の最大長 * * @return @a buf へのポインタ, あるいはエラー時はNULLを返す. * * * Receive message from server for one line, and store it to buffer. * The newline character at end will be stripped. * * @param sd [in] socket descriptor to receive data * @param buf [out] buffer to store the received message string. * @param maxlen [in] maximum allowed length of @a buf * * @return pointer equal to @a buf, or NULL if error. * */ char * do_receive(int sd, char *buf, int maxlen) { int cnt; char *p; p = buf; while(1) { #ifdef WINSOCK cnt = recv(sd, p, 1, 0); #else cnt = read(sd, p, 1); #endif if (cnt <= 0) return NULL; /* eof or error */ if (*p == '\n' && p > buf) { *p = '\0'; break; } else { if (++p >= buf + maxlen) { fprintf(stderr,"Error: do_receive: line too long (> %d)\n", maxlen); exit(1); } } } return buf; }