sockets.c

来自「mcf5307实验源代码」· C语言 代码 · 共 1,494 行 · 第 1/5 页

C
1,494
字号
        else if(socket_list[socketd]->block != NU_TRUE)
        {
            /* Blocking is not desired so indicate that no connection was made. */
            return_status = NU_NO_TASK_MATCH;
            break;
        }
        else /* no match in task table */
        {
            /* start at the head of the list */
            Task_Entry = Task_Head;

            /* verify that the list is not empty */
            while (Task_Entry != NU_NULL)
            {
                /* discontinue searching if a match is found */
                if ((Task_Entry->Task_ID == Task_ID) &&
                  (Task_Entry->local_port_num == server_port_num))
                {
                    break;
                }
                /* continue checking the next structure */
                Task_Entry = Task_Entry->next;
            }

            /* Indicate that this task is accepting connections. */
            Task_Entry->acceptFlag = 1;

            /* Setup the Task ID field so that this task can be resumed. */
            Task_Entry->Task_ID = Task_ID;

            /*  Let others in while we are waiting for the connection.  */
            suspend_task(Task_ID);

            /* Clear the accept flag. */
            Task_Entry->acceptFlag = 0;

            Task_Entry = NU_NULL;
        }

    }while (Task_Entry == NU_NULL);   /*  while waiting for a task entry. */

    /* allow others to use the TCP resource */
#ifdef PLUS
    NU_Release_Semaphore(&TCP_Resource);
#else
    NU_Release_Resource(TCP_Resource);
#endif

    /* return the new socket descriptor to the server */
    return(return_status);

} /* end of NU_Accept  */

/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      NU_Send                                                          */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*   This function is responsible for transmitting data across a         */
/*   network during a connection-oriented transfer.                      */
/*                                                                       */
/*  CALLED FROM                                                          */
/*                                                                       */
/*      User Applications                                                */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      NU_Obtain_Semaphore                                              */
/*      NU_Release_Semaphore                                             */
/*      NU_GetPnum                                                       */
/*      netwrite                                                         */
/*                                                                       */
/*   History:                                                            */
/*       created - 10/8/92, bgh                                          */
/*                                                                       */
/*************************************************************************/
int16 NU_Send(int16 socketd, char *buff, uint16 nbytes, int16 flags)
{
    uint16 bytes_to_go;                      /* number of bytes yet to transmit */
    int16 count = 0;                         /* number of bytes written */
    int16 curr_count;                        /* number of bytes written this call */
	int16 port_num, pnum;                    /* local machine's port number */
    int16 return_status = NU_NO_PORT_NUMBER; /* initialized to error status */
    struct port *pprt;
    int16   status = 0;

    /*  Clean up warnings.  This parameter is used for socket compatibility
        but we are currently not making any use of it.  */
    unused_parameter = flags;

    /*  Validate the socket number.  */
    if ((socketd < 0) || (socketd >= NSOCKETS) ||
        (socket_list[socketd] == NU_NULL))
        return(NU_INVALID_SOCKET);

    /*  Don't let anyone else in until we are through.  */
#ifdef PLUS
    NU_Obtain_Semaphore(&TCP_Resource, NU_SUSPEND);
#else
    NU_Request_Resource(TCP_Resource, NU_WAIT_FOREVER);
#endif
      
    /* retrieve the local port number from the socket descriptor */
    port_num = socket_list[socketd]->local_addr.port_num;

    /* initialize the byte counters */
    count = 0;
	bytes_to_go = nbytes;
      
    /* verify that a port number exists */
    if (port_num)
    {
        /* get the portlist entry number for this connection */
        if ((pnum = NU_GetPnum(socket_list[socketd])) >= 0)
        {
            while ((bytes_to_go > 0))
            {
                /* call tcp/ip library netwrite routine */
                curr_count = netwrite((uint16)pnum, (buff + count),
									   bytes_to_go, &status);

                /* If 0 was returned, then for some reason we failed to send the
                   data.  Check to see if we failed because we have already
                   filled up the window of the remote host.  If so just
                   continue.  We will suspend below, and be awakened when the
                   remote host acks some of the data we have already sent.  At
				   that point some more data can be transmitted.  If we failed
                   for any other reason check to see if some data has already
                   been sent.  If so return the number of bytes that have
                   already been sent.  If no data has been sent (i.e., count ==
                   0) then set count equal to the error code so the application
                   layer will see the error.
                */
                if (curr_count == 0)
                {
					// modified by Ason. (1998.8.4.)
					/*
					if (status == NU_WINDOW_FULL)
					{
					   status = -1972;
					   break;
					}
					*/

					if (status != NU_WINDOW_FULL)
					{
						if (count == 0)
							count = curr_count;
						break;
					}
				}

				/* update the bytes counter */
				bytes_to_go -= curr_count;

				/* update the total bytes sent */
				count += curr_count;

				/* If the number of bytes to go indicates more to be sent
				   then suspend until there are buffers available. */
				if (bytes_to_go > 0)
				{

					// modified by Ason. (1998.8.4.)
					/*
					status = -1973;
					break;
					*/

					pprt = portlist[pnum];

					/* Increment the number of tasks that are waiting for
						buffers before they can send. */
					tasks_waiting_to_send++;

#ifdef PLUS
                    pprt->TXTask = NU_Current_Task_Pointer();
					suspend_task(pprt->TXTask);
					pprt->TXTask = NU_NULL;
#else /* RXT */
					pprt->TXTask = NU_Current_Task_ID();
					suspend_task(pprt->TXTask);
                    pprt->TXTask = -1;
#endif /* PLUS */

				} /* still bytes to be sent */

			} /* while still bytes to transmit. */

			/* verify success of transfer, if a code of less than
			 * zero is received that means that the connection
			 * is broken, the return_status is set up to
			 * indicate that. */
            if ((status == NU_SUCCESS) && (count >= 0))
                /* return number of bytes transferred */
                return_status = count;
            else
                return_status = status;
		}
    }
           
    /* allow others to use the TCP resource */
#ifdef PLUS
    NU_Release_Semaphore(&TCP_Resource);
#else
    NU_Release_Resource(TCP_Resource);
#endif
      
    /* return to caller */
    return(return_status);

}  /*  end of NU_Send  */

/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      NU_Send_To                                                       */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*   This function is responsible for transmitting data across           */
/*   a network during a connectionless transfer.                         */
/*                                                                       */
/*  CALLED FROM                                                          */
/*                                                                       */
/*      User Applications                                                */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      NU_Obtain_Semaphore                                              */
/*      NU_Release_Semaphore                                             */
/*      NU_Get_UDP_Pnum                                                  */
/*      makeuport                                                        */
/*      intswap                                                          */
/*      netusend                                                         */
/*                                                                       */
/*   History:                                                            */
/*       created - 10/8/92, bgh                                          */
/*                                                                       */
/*************************************************************************/
int16 NU_Send_To(int16 socketd, char *buff, uint16 nbytes, int16 flags,
     struct addr_struct *to, int16 addrlen)
{
    int16 count;                              /* number of bytes written */
    struct uport       *uprt;
    struct sock_struct *sockptr;            /* pointer to current socket */
    int16 port_num;                          /* local machine's port number */
    int16 return_status = NU_NO_PORT_NUMBER;  /* initialized to error status */
    uint16 dest_port;
    
    /*  Clean up warnings.  This parameter is used for socket compatibility
     *  but we are currently not making any use of it.  */
    unused_parameter = flags;
    unused_parameter = addrlen;

    /*  Validate the socket number.  */
    if ((socketd < 0) || (socketd >= NSOCKETS) ||
                (socket_list[socketd] == NU_NULL))
        return(NU_INVALID_SOCKET);

    /* added 11/3/92 - reserve the resource */
#ifdef PLUS
    NU_Obtain_Semaphore(&TCP_Resource, NU_SUSPEND);
#else
    NU_Request_Resource(TCP_Resource, NU_WAIT_FOREVER);
#endif

    /* Pick up a pointer to the socket list entry.  */
    sockptr = socket_list[socketd];

    /* get the server's port number */
    dest_port = to->port;

    /* verify that a port number exists */
    if (dest_port)
    {
        /*  Make sure that he gave us the IP number. */
        if (comparen (to->id.is_ip_addrs, (VOID *)nullip, 4))
        {
            /* allow others to use the TCP resource */
#ifdef PLUS
            NU_Release_Semaphore(&TCP_Resource);
#else
            NU_Release_Resource(TCP_Resource);
#endif
      
            return(NU_INVALID_ADDRESS);
        }

        /* Pick up the foreign IP address and port number. */
        sockptr->foreign_addr.port_num = (int16)dest_port;
        memcpy(&(sockptr->foreign_addr.ip_num), &(to->id), 4);

        /*  Make a port for this send if one does not already exist. */
        if (sockptr->local_addr.port_num > 0)

⌨️ 快捷键说明

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