⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sockets.c

📁 Open DMT Client C Source code
💻 C
📖 第 1 页 / 共 2 页
字号:
// ----------------------------------------------------------------------------// Copyright 2006-2007, Martin D. Flynn// All rights reserved// ----------------------------------------------------------------------------//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at// // http://www.apache.org/licenses/LICENSE-2.0// // Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.//// ----------------------------------------------------------------------------// Description://  Example UDP/TCP socket utilities for data transport use.// ---// Change History://  2006/01/04  Martin D. Flynn//     -Initial release//  2006/01/12  Martin D. Flynn//     -Fixed read timeout problem on Linux.//  2007/01/28  Martin D. Flynn//     -WindowsCE port//     -Enabled non-blocking mode on tcp sockets (TARGET_WINCE only)//     -Added 'send' select check (see 'socketIsSendReady')//     -Fixed premature timeout problem in socketReadTCP//  2007/02/05  Martin D. Flynn//     -Fixed size of 'heBuf' in call to 'gethostbyname_r'.  Was 256, which was//      too small for uClibc. (Thanks to Tomasz Rostanski for catching this!).// ----------------------------------------------------------------------------#include "stdafx.h" // TARGET_WINCE#define SKIP_TRANSPORT_MEDIA_CHECK // only if TRANSPORT_MEDIA not used in this file #include "custom/defaults.h"#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <ctype.h>#include <time.h>#include <string.h>#include <limits.h>#if defined(TARGET_WINCE)#  include <winsock2.h>typedef int socklen_t;#else#  include <unistd.h>#  include <errno.h>#  include <termios.h>#  include <netdb.h>#  include <netinet/in.h>#  include <sys/types.h>#  include <sys/ioctl.h>#  include <sys/stat.h>#  include <sys/socket.h>#  include <sys/select.h>#endif#include "tools/stdtypes.h"#include "tools/strtools.h"#include "tools/utctools.h"#include "tools/sockets.h"#include "custom/log.h"// ----------------------------------------------------------------------------#define ALWAYS_RESOLVE_HOST     utFalse// ----------------------------------------------------------------------------// Overhead://  TCP => 20(IP) + 20{TCP) = 40//  UDP => 20(IP) +  8(UDP) = 28// Minimum IP datagram size = 576 bytes (include the above overhead)// Maximum IP datagram size = 65516//// Protocol overhead: http://sd.wareonearth.com/~phil/net/overhead/// ----------------------------------------------------------------------------#if   defined(TARGET_CYGWIN)// This works on Cygwin#  define IOCTIL_REQUEST_BYTES_AVAIL    TIOCINQ     // (int*) Cygwin#  define CLOSE_SOCKET(F)               close(F)#  define IOCTL_SOCKET(F,R,A)           ioctl(F,R,A)#  define IOCTL_ARG_TYPE                int#  define INVALID_SOCKET                (-1)#  define SOCKET_ERROR                  (-1)#elif defined(TARGET_WINCE)// Windows CE#  define IOCTIL_REQUEST_BYTES_AVAIL    FIONREAD    // (u_long*) Windows CE#  define IOCTIL_REQUEST_NON_BLOCKING   FIONBIO     // (u_long*) Windows CE#  define CLOSE_SOCKET(F)               closesocket(F)#  define IOCTL_SOCKET(F,R,A)           ioctlsocket(F,R,A)  // [A=(ulong*)]#  define IOCTL_ARG_TYPE                u_long//#  define INVALID_SOCKET              (-1)        <- already defined//#  define SOCKET_ERROR                (-1)        <- already defined#else// This works fine on Linux and GumStix#  include <asm/ioctls.h>#  define IOCTIL_REQUEST_BYTES_AVAIL    FIONREAD    // (int*)//#  define IOCTIL_REQUEST_NON_BLOCKING FIONBIO     // (int*)#  define CLOSE_SOCKET(F)               close(F)#  define IOCTL_SOCKET(F,R,A)           ioctl(F,R,A)#  define IOCTL_ARG_TYPE                int#  define INVALID_SOCKET                (-1)#  define SOCKET_ERROR                  (-1)#endif// ----------------------------------------------------------------------------// Windows CE 'errno' redefinitions#if defined(TARGET_WINCE)#  define RESET_ERRNO                   WSASetLastError(0) // docs claim this is required#  define ERRNO                         WSAGetLastError() // 'errno' undefined on WinCE#  define ECONNRESET                    WSAECONNRESET#  define EWOULDBLOCK                   WSAEWOULDBLOCK#  define EAGAIN                        WSAEWOULDBLOCK#else#  define ERRNO                         errno#  define RESET_ERRNO                   /*NO-OP*/ // errno = 0#endif// ----------------------------------------------------------------------------/* client/server: clear socket structure */void socketInitStruct(Socket_t *sock, const char *host, int port, int type){    if (sock) {        memset(sock, 0, sizeof(Socket_t));#if defined(ENABLE_SERVER_SOCKET)        sock->serverfd = INVALID_SOCKET;#endif        sock->sockfd = INVALID_SOCKET;        sock->type = type; // SOCK_DGRAM/SOCK_STREAM        if (host) {            int len = strLength(host, sizeof(sock->host) - 1);            strncpy(sock->host, host, len);            sock->host[len] = 0;        }        sock->port = port;    }}// ----------------------------------------------------------------------------static int socketResolveHost(const char *host, UInt8 *addr, utBool alwaysResolve){    // Note: 'addr' is assumed to be 6 bytes in length    /* invalid addr */    if (!addr) {        return COMERR_SOCKET_HOST;    }    /* check for already resolved */    if (!alwaysResolve) {        // don't resolve if address has already been resolved        // [NOTE: may have no effect if the socket structure is initialized to nulls on each open]        int i;        for (i = 0; i < 6; i++) {            if (addr[i]) {                return COMERR_SUCCESS;            }        }    }    /* invalid host name */    if (!host || !*host) {        return COMERR_SOCKET_HOST;    }        /* get host entry */    struct hostent *he = (struct hostent*)0;#if defined(TARGET_LINUX)    // thread safe    struct hostent rhe;    char heBuf[512]; // was 256 - (too small for uClibc)    // Exact size would be '460':    //    sizeof(struct in_addr) +    //    sizeof(struct in_addr*)*2 +     //    sizeof(char*)*(ALIAS_DIM) +  // (ALIAS_DIM is (2 + 5/*MAX_ALIASES*/ + 1))    //    384/*namebuffer*/ +     //    32/*margin*/;    int heErrno = 0;    gethostbyname_r(host, &rhe, heBuf, sizeof(heBuf), &he, &heErrno);#elif defined(TARGET_WINCE)    // not thread safe    WSASetLastError(0);    he = gethostbyname(host); // this may fail if 'host' contains an IP address    int heErrno = WSAGetLastError(); // WSAHOST_NOT_FOUND [11001]    if (!he && isdigit(*host)) { // <-- simple test for IP address        logWARNING(LOGSRC,"Attempting to parse IP address: %s", host);        u_long ipAddr = inet_addr(host);        if (ipAddr != INADDR_NONE) {            he = gethostbyaddr((char*)&ipAddr, 4, AF_INET);            if (he) {                logINFO(LOGSRC,"Successful at obtaining hostent from IP address!");                heErrno = 0;            } else {                heErrno = WSAGetLastError();            }        } else {            logWARNING(LOGSRC,"Unable to parse IP address");        }    }#else    // not thread safe    he = gethostbyname(host);    int heErrno = h_errno;#endif    /* extract address */    if (he) {        int len = (he->h_length < 6)? he->h_length : 6;        memcpy(addr, he->h_addr_list[0], len);        return COMERR_SUCCESS;    } else {        logWARNING(LOGSRC,"Unable to resolve host [%d]: %s", heErrno, host);        return COMERR_SOCKET_HOST;    }    }// ----------------------------------------------------------------------------/* enable non-blocking mode */utBool socketEnableNonBlockingClient(Socket_t *sock, utBool enable){#if defined(IOCTIL_REQUEST_NON_BLOCKING)    if (sock && (sock->sockfd != INVALID_SOCKET)) {        IOCTL_ARG_TYPE enableNonBlocking = enable? 1 : 0;        RESET_ERRNO; // WSASetLastError(0);        int status = IOCTL_SOCKET(sock->sockfd, IOCTIL_REQUEST_NON_BLOCKING, &enableNonBlocking);        if (status >= 0) {            sock->nonBlock = enable;            //logINFO(LOGSRC,"Socket set to non-blocking mode");            return utTrue;        } else {            int err = ERRNO; // WSAGetLastError();            logERROR(LOGSRC,"Unable to enable non-blocking mode [errno=%d]", err);            return utFalse;        }    }#endif    return utFalse;}/* return true if non-blocking mode has been set for this client socket */utBool socketIsNonBlockingClient(Socket_t *sock){    if (sock && (sock->sockfd != INVALID_SOCKET)) {        return sock->nonBlock;    } else {        return utFalse;    }}// ----------------------------------------------------------------------------/* client: open a UDP socket for writing */int socketOpenUDPClient(Socket_t *sock, const char *host, int port){    /* create socket */    socketInitStruct(sock, host, port, SOCK_DGRAM);    sock->sockfd = socket(AF_INET, SOCK_DGRAM, 0);    if (sock->sockfd < 0) {        // unlikely to occur        return COMERR_SOCKET_OPEN;    }    /* resolve hostname */    int err = socketResolveHost(host, sock->hostAddr, ALWAYS_RESOLVE_HOST);    if (err != COMERR_SUCCESS) {        //fprintf(stderr, "Unable to resolve host: %s\n", host);        CLOSE_SOCKET(sock->sockfd);        sock->sockfd = INVALID_SOCKET;        return COMERR_SOCKET_HOST;    }    return COMERR_SUCCESS;}/* server: open a UDP socket for reading */#if defined(ENABLE_SERVER_SOCKET)int socketOpenUDPServer(Socket_t *sock, int port){    /* create socket */    socketInitStruct(sock, (char*)0, port, SOCK_DGRAM);    sock->sockfd = socket(AF_INET, SOCK_DGRAM, 0);    if (sock->sockfd < 0) {        // unlikely to occur        return COMERR_SOCKET_OPEN;    }            /* bind to local port (RX only) */    struct sockaddr_in my_addr;             // connector's address information    my_addr.sin_family = AF_INET;           // host byte order    my_addr.sin_port = htons(sock->port);   // short, network byte order    my_addr.sin_addr.s_addr = INADDR_ANY;    if (bind(sock->sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr)) == -1) {        // Unable to bind server to specified port        //fprintf(stderr, "Unable to bind to port %d\n", port);        CLOSE_SOCKET(sock->sockfd);        sock->sockfd = INVALID_SOCKET;        return COMERR_SOCKET_BIND;    }    return COMERR_SUCCESS;}#endif// ----------------------------------------------------------------------------/* client: open a TCP client socket */int socketOpenTCPClient(Socket_t *sock, const char *host, int port){    /* init socket */    socketInitStruct(sock, host, port, SOCK_STREAM);    sock->sockfd = socket(AF_INET, SOCK_STREAM, 0); // SOCK_DGRAM    if (sock->sockfd == INVALID_SOCKET) {        // unlikely to occur        return COMERR_SOCKET_OPEN;    }    /* resolve hostname */    int err = socketResolveHost(host, sock->hostAddr, ALWAYS_RESOLVE_HOST);    if (err != COMERR_SUCCESS) {        //fprintf(stderr, "Unable to resolve host: %s\n", host);        CLOSE_SOCKET(sock->sockfd);        sock->sockfd = INVALID_SOCKET;        return COMERR_SOCKET_HOST;    }    /* connect */    struct sockaddr_in their_addr; // connector's address information    their_addr.sin_family = AF_INET;      // host byte order    their_addr.sin_port   = htons(port);  // short, network byte order    their_addr.sin_addr   = *((struct in_addr *)sock->hostAddr);    memset(&(their_addr.sin_zero), 0, sizeof(their_addr.sin_zero));  // (8) zero the rest of the struct    RESET_ERRNO; // WSASetLastError(0);    if (connect(sock->sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) < 0) {        // Unable to connect to specified host:port        int err = ERRNO;        logERROR(LOGSRC,"Unable to establish socket connect [errno=%d]", err);        CLOSE_SOCKET(sock->sockfd);        sock->sockfd = INVALID_SOCKET;        return COMERR_SOCKET_CONNECT;    }        /* non-blocking mode */#if defined(TARGET_WINCE)    // set non-blocking AFTER connection    socketEnableNonBlockingClient(sock, utTrue);#endif    /* send timeout (SO_SNDTIMEO) */    //(This is not supported on all platforms)    //struct timeval timeo;    //utcGetTimestampDelta(&timeo, 10000L);    //if (setsockopt(sock->sockfd, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeo, sizeof(timeo)) == -1) {    //    // Unable to set client socket options    //    CLOSE_SOCKET(sock->sockfd);    //    sock->sockfd = INVALID_SOCKET;    //    return COMERR_SOCKET_OPTION;    //}    /* success */    return COMERR_SUCCESS;}/* server: is client socket open */utBool socketIsOpenClient(Socket_t *sock){    return (sock && (sock->sockfd != INVALID_SOCKET))? utTrue : utFalse;}// ----------------------------------------------------------------------------#if defined(ENABLE_SERVER_SOCKET)/* server: open a TCP server socket */int socketOpenTCPServer(Socket_t *sock, int port){    /* init */    socketInitStruct(sock, 0, port, SOCK_STREAM);    /* socket */    sock->serverfd = socket(AF_INET, SOCK_STREAM, 0); // SOCK_DGRAM    if (sock->serverfd == INVALID_SOCKET) {        return COMERR_SOCKET_OPEN;    }        /* reuse address */    int yes = 1;    if (setsockopt(sock->serverfd, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(int)) == -1) {        // Unable to set server socket options        CLOSE_SOCKET(sock->serverfd);        sock->serverfd = INVALID_SOCKET;        return COMERR_SOCKET_OPTION;    }        /* send timeout? (SO_SNDTIMEO) */    /* linger on close */    struct linger so_linger;    so_linger.l_onoff  = 1; // linger on    so_linger.l_linger = 2; // 2 seconds    if (setsockopt(sock->serverfd, SOL_SOCKET, SO_LINGER, (char*)&so_linger, sizeof(struct linger)) == -1) {        // Unable to set server socket options        CLOSE_SOCKET(sock->serverfd);        sock->serverfd = INVALID_SOCKET;        return COMERR_SOCKET_OPTION;    }    /* bind to port */    struct sockaddr_in my_addr;             // my address information    my_addr.sin_family = AF_INET;           // host byte order    my_addr.sin_port = htons(sock->port);   // short, network byte order    my_addr.sin_addr.s_addr = INADDR_ANY;   // auto-fill with my IP    memset(&my_addr.sin_zero, 0, 8); // zero the rest of the struct    if (bind(sock->serverfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {        // Unable to bind server to specified port        CLOSE_SOCKET(sock->serverfd);        sock->serverfd = INVALID_SOCKET;        return COMERR_SOCKET_BIND;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -