📄 sock.c
字号:
/******************************************************************************//* * Add one to allow the user to write exactly SOCKET_BUFSIZ */void socketSetBufferSize(int sid, int in, int line, int out){ socket_t *sp; if ((sp = socketPtr(sid)) == NULL) { return; } if (in >= 0) { ringqClose(&sp->inBuf); in++; ringqOpen(&sp->inBuf, in, in); } if (line >= 0) { ringqClose(&sp->lineBuf); line++; ringqOpen(&sp->lineBuf, line, line); } if (out >= 0) { ringqClose(&sp->outBuf); out++; ringqOpen(&sp->outBuf, out, out); }}/******************************************************************************//* * Create a user handler for this socket. The handler called whenever there * is an event of interest as defined by handlerMask (SOCKET_READABLE, ...) */void socketCreateHandler(int sid, int handlerMask, socketHandler_t handler, int data){ socket_t *sp; if ((sp = socketPtr(sid)) == NULL) { return; } sp->handler = handler; sp->handler_data = data; socketRegisterInterest(sp, handlerMask);}/******************************************************************************//* * Delete a handler */void socketDeleteHandler(int sid){ socket_t *sp; if ((sp = socketPtr(sid)) == NULL) { return; } sp->handler = NULL; socketRegisterInterest(sp, 0);}/******************************************************************************//* * Socket output procedure. Return -1 on errors otherwise return the number * of bytes written. */static int socketDoOutput(socket_t *sp, char *buf, int toWrite, int *errCode){ struct sockaddr_in server; int bytes; a_assert(sp); a_assert(buf); a_assert(toWrite > 0); a_assert(errCode); *errCode = 0;#if WIN || CE if ((sp->flags & SOCKET_ASYNC) && ! socketWaitForEvent(sp, FD_CONNECT, errCode)) { return -1; }#endif/* * Write the data */ if (sp->flags & SOCKET_BROADCAST) { server.sin_family = AF_INET;#if UEMF || LITTLEFOOT server.sin_addr.s_addr = INADDR_BROADCAST;#else server.sin_addr.s_addr = inet_addr(basicGetBroadcastAddress());#endif server.sin_port = htons((short)(sp->port & 0xFFFF)); if ((bytes = sendto(sp->sock, buf, toWrite, 0, (struct sockaddr *) &server, sizeof(server))) < 0) { bytes = tryAlternateSendTo(sp->sock, buf, toWrite, 0, (struct sockaddr *) &server); } } else if (sp->flags & SOCKET_DATAGRAM) { server.sin_family = AF_INET; server.sin_addr.s_addr = inet_addr(sp->host); server.sin_port = htons((short)(sp->port & 0xFFFF)); bytes = sendto(sp->sock, buf, toWrite, 0, (struct sockaddr *) &server, sizeof(server)); } else { bytes = send(sp->sock, buf, toWrite, 0); } if (bytes < 0) { *errCode = socketGetError();#if WIN || CE sp->currentEvents &= ~FD_WRITE;#endif return -1; } else if (bytes == 0 && bytes != toWrite) { *errCode = EWOULDBLOCK;#if WIN || CE sp->currentEvents &= ~FD_WRITE;#endif return -1; }/* * Ensure we get to write some more data real soon if the socket can absorb * more data */#if !UEMF#if WIN if (sp->interestEvents & FD_WRITE) { emfTime_t blockTime = { 0, 0 }; emfSetMaxBlockTime(&blockTime); }#endif /* WIN */#endif return bytes;}/******************************************************************************//* * If the sendto failed, swap the first two bytes in the * sockaddr structure. This is a kludge due to a change in * VxWorks between versions 5.3 and 5.4, but we want the * product to run on either. */static int tryAlternateSendTo(int sock, char *buf, int toWrite, int i, struct sockaddr *server){#if VXWORKS char *ptr; ptr = (char *)server; *ptr = *(ptr+1); *(ptr+1) = 0; return sendto(sock, buf, toWrite, i, server, sizeof(struct sockaddr));#else return -1;#endif /* VXWORKS */}/******************************************************************************//* * Allocate a new socket structure */int socketAlloc(char *host, int port, socketAccept_t accept, int flags){ socket_t *sp; int sid; if ((sid = hAllocEntry((void***) &socketList, &socketMax, sizeof(socket_t))) < 0) { return -1; } sp = socketList[sid]; sp->sid = sid; sp->accept = accept; sp->port = port; sp->fileHandle = -1; sp->saveMask = -1; if (host) { strncpy(sp->host, host, sizeof(sp->host)); }/* * Preserve only specified flags from the callers open */ a_assert((flags & ~(SOCKET_BROADCAST|SOCKET_DATAGRAM|SOCKET_BLOCK| SOCKET_LISTENING)) == 0); sp->flags = flags & (SOCKET_BROADCAST | SOCKET_DATAGRAM | SOCKET_BLOCK| SOCKET_LISTENING);/* * Add one to allow the user to write exactly SOCKET_BUFSIZ */ ringqOpen(&sp->inBuf, SOCKET_BUFSIZ, SOCKET_BUFSIZ); ringqOpen(&sp->outBuf, SOCKET_BUFSIZ + 1, SOCKET_BUFSIZ + 1); ringqOpen(&sp->lineBuf, SOCKET_BUFSIZ, -1); return sid;}/******************************************************************************//* * Free a socket structure */void socketFree(int sid){ socket_t *sp; char_t buf[256]; int i; if ((sp = socketPtr(sid)) == NULL) { return; }/* * To close a socket, remove any registered interests, set it to * non-blocking so that the recv which follows won't block, do a * shutdown on it so peers on the other end will receive a FIN, * then read any data not yet retrieved from the receive buffer, * and finally close it. If these steps are not all performed * RESETs may be sent to the other end causing problems. */ socketRegisterInterest(sp, 0); if (sp->sock >= 0) { socketSetBlock(sid, 0); if (shutdown(sp->sock, 1) >= 0) { recv(sp->sock, buf, sizeof(buf), 0); }#if WIN || CE closesocket(sp->sock);#else close(sp->sock);#endif } ringqClose(&sp->inBuf); ringqClose(&sp->outBuf); ringqClose(&sp->lineBuf); bfree(B_L, sp); socketMax = hFree((void***) &socketList, sid);/* * Calculate the new highest socket number */ socketHighestFd = -1; for (i = 0; i < socketMax; i++) { if ((sp = socketList[i]) == NULL) { continue; } socketHighestFd = max(socketHighestFd, sp->sock); }}/******************************************************************************//* * Validate a socket handle */socket_t *socketPtr(int sid){ if (sid < 0 || sid >= socketMax || socketList[sid] == NULL) { a_assert(NULL); errno = EBADF; return NULL; } a_assert(socketList[sid]); return socketList[sid];}/******************************************************************************//* * Get the operating system error code */int socketGetError(){#if WIN || CE switch (WSAGetLastError()) { case WSAEWOULDBLOCK: return EWOULDBLOCK; case WSAECONNRESET: return ECONNRESET; case WSAENETDOWN: return ENETDOWN; case WSAEPROCLIM: return EAGAIN; case WSAEINTR: return EINTR; default: return EINVAL; }#else return errno;#endif}/******************************************************************************//* * Return the underlying socket handle */int socketGetHandle(int sid){ socket_t *sp; if ((sp = socketPtr(sid)) == NULL) { return -1; } return sp->sock;}/******************************************************************************//* * Get blocking mode */int socketGetBlock(int sid){ socket_t *sp; if ((sp = socketPtr(sid)) == NULL) { a_assert(0); return 0; } return (sp->flags & SOCKET_BLOCK);}/******************************************************************************//* * Get mode */int socketGetMode(int sid){ socket_t *sp; if ((sp = socketPtr(sid)) == NULL) { a_assert(0); return 0; } return sp->flags;}/******************************************************************************//* * Set mode */void socketSetMode(int sid, int mode){ socket_t *sp; if ((sp = socketPtr(sid)) == NULL) { a_assert(0); return; } sp->flags = mode;}/******************************************************************************//* * Get port. */int socketGetPort(int sid){ socket_t *sp; if ((sp = socketPtr(sid)) == NULL) { return -1; } return sp->port;}/******************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -