📄 closesock.c
字号:
/***********************************************************************//* *//* Module: close.c *//* Release: 2001.3 *//* Version: 99.0 *//* Purpose: closesocket() implementation *//* *//*---------------------------------------------------------------------*//* *//* Copyright 1999, Blunk Microsystems *//* ALL RIGHTS RESERVED *//* *//* Licensees have the non-exclusive right to use, modify, or extract *//* this computer program for software development at a single site. *//* This program may be resold or disseminated in executable format *//* only. The source code may not be redistributed or resold. *//* *//***********************************************************************/#include "../tcp_ipp.h"#include "../tcp/tcp.h"/***********************************************************************//* Symbol Definitions *//***********************************************************************/#define MAX_FIN_WAIT (600 * TICKS_PER_SEC)/***********************************************************************//* Local Function Definitions *//***********************************************************************//***********************************************************************//* tcp_close: Close TCP socket *//* *//* Input: sock = pointer to a TCP socket control block *//* *//* Returns: 0 if no errors, else -1 with errno set to error code *//* *//***********************************************************************/static int tcp_close(SOCKET sock){ int rb_count = sock->rb_count; /*-------------------------------------------------------------------*/ /* Free socket receive buffer, queued receive buffers, and OOS queue.*/ /*-------------------------------------------------------------------*/ TcpStrip(sock, FREE_RBUF); /*-------------------------------------------------------------------*/ /* Only send FIN if ESTABLISHED, CLOSE_WAIT, or SYN_RCVD. */ /*-------------------------------------------------------------------*/ switch (sock->state) { case SS_SYNRCVD: /* send FIN */ case SS_ESTABLISHED: /* send FIN */ case SS_FINWAIT1: case SS_FINWAIT2: /*---------------------------------------------------------------*/ /* Set maximum wait for peer's FIN. */ /*---------------------------------------------------------------*/ NetTimerStart(&sock->state_tmr, MAX_FIN_WAIT); break; case SS_CLOSING: case SS_CLOSEWAIT: /* send FIN */ /*---------------------------------------------------------------*/ /* Already received peer's FIN. */ /*---------------------------------------------------------------*/ break; default: /*---------------------------------------------------------------*/ /* Connection already closed. Return success. */ /*---------------------------------------------------------------*/ return 0; } /*-------------------------------------------------------------------*/ /* Check if forceful close requested or received data remained. */ /*-------------------------------------------------------------------*/ if ((sock->flags & SF_FORCEFUL) || rb_count) { sock->flags |= TCPF_RST; TcpSendSeg(sock, 0); TcpDrop(sock, ECONNABORTED); return 0; } /*-------------------------------------------------------------------*/ /* Check if FIN needs to be sent. */ /*-------------------------------------------------------------------*/ if ((sock->flags & SF_SND_SHUT) == FALSE) { /*-----------------------------------------------------------------*/ /* Record FIN request and its sequence number. */ /*-----------------------------------------------------------------*/ sock->flags |= SF_SNDFIN; sock->fin_seq = sock->snt_una + sock->sb_count; /*-----------------------------------------------------------------*/ /* Start output state machine. */ /*-----------------------------------------------------------------*/ TcpTryOut(sock); /*-----------------------------------------------------------------*/ /* Update state to either FIN_WAIT_1 or LAST_ACK. */ /*-----------------------------------------------------------------*/ if ((sock->state == SS_CLOSEWAIT) || (sock->flags & SF_OOOFIN)) sock->state = SS_LASTACK; else /* state == ESTABLISHED or SYN_RCVD */ sock->state = SS_FINWAIT1; } /*-------------------------------------------------------------------*/ /* Check if socket has been configured to linger on closesocket(). */ /*-------------------------------------------------------------------*/ if (sock->flags & SF_LINGER) { /*-----------------------------------------------------------------*/ /* If non-blocking, report error and return -1. */ /*-----------------------------------------------------------------*/ if (sock->flags & SF_NONBLKNG) { NetError(NULL, EWOULDBLOCK); return -1; } /*-----------------------------------------------------------------*/ /* Else wait for "closed" event and check for timeout. */ /*-----------------------------------------------------------------*/ else { NetPendEvent(sock, SE_CLOSED, WAIT_FOREVER); if (sock->error) { NetError(NULL, sock->error); return -1; } } } /*-------------------------------------------------------------------*/ /* Return 0 for success. */ /*-------------------------------------------------------------------*/ return 0;}/***********************************************************************//* Global Function Definitions *//***********************************************************************//***********************************************************************//* closesocket: Public API for closing TCP or UDP socket *//* *//* Input: s = socket identifier *//* *//* Returns: 0 if no errors, else -1 with errno set to error code *//* *//***********************************************************************/int closesocket(int s){ SOCKET sock = &Socks[s - 1]; int rc = 0;#if OS_PARM_CHECK /*-------------------------------------------------------------------*/ /* Verify protocol has been initialized. */ /*-------------------------------------------------------------------*/ if (!Net.Initialized) { NetError(NULL, ENETDOWN); return -1; } /*-------------------------------------------------------------------*/ /* Check for valid socket ID. */ /*-------------------------------------------------------------------*/ if (InvalidHandle(s)) { NetError(NULL, ENOTSOCK); return -1; }#endif /*-------------------------------------------------------------------*/ /* Acquire exclusive access to stack internals. */ /*-------------------------------------------------------------------*/ semPend(Net.IntSem, WAIT_FOREVER); /*-------------------------------------------------------------------*/ /* Return error if socket is in process of being closed. */ /*-------------------------------------------------------------------*/ if (sock->error == ENOTSOCK) { NetError(NULL, ENOTSOCK); return -1; } /*-------------------------------------------------------------------*/ /* Record that socket is being closed. */ /*-------------------------------------------------------------------*/ sock->error = ENOTSOCK; /*-------------------------------------------------------------------*/ /* Free any tasks blocked on this socket. */ /*-------------------------------------------------------------------*/ if (sock->events || sock->sel_evnts) NetPostEvent(sock, SE_ERROR); /*-------------------------------------------------------------------*/ /* Release exclusive access to internals and wait for API access. */ /*-------------------------------------------------------------------*/ semPost(Net.IntSem); if (semPend(sock->api_access, WAIT_FOREVER)) { NetError(NULL, ENOTSOCK); return -1; } /*-------------------------------------------------------------------*/ /* Re-acquire exclusive access to stack internals. */ /*-------------------------------------------------------------------*/ semPend(Net.IntSem, WAIT_FOREVER); /*-------------------------------------------------------------------*/ /* Delete the API access semaphore and clear its handle. */ /*-------------------------------------------------------------------*/ semDelete(sock->api_access); sock->api_access = (SEM)NULL; /*-------------------------------------------------------------------*/ /* If UDP socket, just post closed event. */ /*-------------------------------------------------------------------*/ if (sock->type == SOCK_DGRAM) NetPostEvent(sock, SE_CLOSED); /*-------------------------------------------------------------------*/ /* Else initiate TCP close. */ /*-------------------------------------------------------------------*/ else rc = tcp_close(sock); /*-------------------------------------------------------------------*/ /* Release socket hold and internal access semaphore. Return status. */ /*-------------------------------------------------------------------*/ SockRelease(sock); semPost(Net.IntSem); return rc;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -