예제 #1
0
void TcpClient::CRecv(char *buf_, size_t length_, long timeout_)
{
	int retval;
	fd_set read_fds;
	size_t recv_bytes = 0;
	struct timeval timeout;
	struct timeval* ptimeout;

	while( recv_bytes != length_ )
	{

		FD_ZERO(&read_fds);
		FD_SET(this->sock_fd, &read_fds);

		// 超时设置
		ptimeout= TranslateTime(timeout_, &timeout);

		// 等待套接字可读
		while((retval = select(this->sock_fd + 1, &read_fds, NULL, NULL, ptimeout)) == -1 
			&& errno == EINTR);

		// select 成功返回
		if ( retval > 0 )
		{
			if (FD_ISSET(this->sock_fd, &read_fds))
			{
				int bytes;

				while( (bytes = recv(this->sock_fd, buf_ + recv_bytes, length_ - recv_bytes, MSG_DONTWAIT)) == -1 
					&& errno == EINTR); 
				
				if(bytes == -1 && errno == EAGAIN)
				{
					continue;
				}
				else if (bytes == 0) // 连接被关闭
				{
					Throw("socket closed by client", 0);
				}
				else if	(bytes	< 0)
				{
					Throw("socket error",errno);
				}

				recv_bytes += bytes;
			}
		}
		else if( retval == 0 )
		{
			Throw("socket time out", 0);
		}
		else
		{
			Throw("select failed", errno);
		}
	}

	return;
}
예제 #2
0
int TcpClient::Send(const char *buf_, size_t length_, long timeout_)
{
	int retval;
	int bytes;
	fd_set write_fds;
	struct timeval timeout;
	struct timeval* ptimeout;
	
	size_t tol = 0;

	while(tol < length_)
	{
		FD_ZERO(&write_fds);
		FD_SET(this->sock_fd, &write_fds);

		// 设置超时
		ptimeout= TranslateTime(timeout_, &timeout);

		// 等待套接字可写
		while((retval = select(this->sock_fd + 1, NULL, &write_fds, NULL, ptimeout)) == -1 
			&& errno == EINTR);

		// select 成功返回
		if( retval > 0 )
		{
			if (FD_ISSET(this->sock_fd, &write_fds))
			{
				// 发送数据
				while( (bytes = send(this->sock_fd, buf_+tol, length_-tol, MSG_DONTWAIT)) == -1 
					&& errno == EINTR );

				if(bytes == -1 && errno == EAGAIN)
				{
					continue;
				}
				else if	(bytes	< 0)
				{
					Throw("socket error",errno);
				}
				else
				{
					tol += bytes;
					//break;
				}
			}
		}
		else if( retval == 0 )
		{
			Throw("Socket time out", 0);
		}
		else
		{
			Throw("Select failed", errno);
		}
	}

	return tol;
}
예제 #3
0
void TcpClient::CSend(const char *buf_, size_t length_, long timeout_)
{
	int retval;
	fd_set write_fds;
	size_t sent_bytes = 0;
	struct timeval timeout;
	struct timeval* ptimeout;

	while(sent_bytes != length_)
	{

		FD_ZERO(&write_fds);
		FD_SET(this->sock_fd, &write_fds);

		// 超时设置
		ptimeout= TranslateTime(timeout_, &timeout);

		// 等待套接字可写
		while((retval = select(this->sock_fd + 1, NULL, &write_fds, NULL, ptimeout)) == -1 
			&& errno == EINTR);

		if( retval > 0 )
		{
			if (FD_ISSET(this->sock_fd, &write_fds))
			{

				int bytes;
				while( (bytes = send(this->sock_fd, buf_ + sent_bytes, length_ - sent_bytes, MSG_DONTWAIT)) == -1 
					&& errno == EINTR );

				if(bytes == -1 && errno == EAGAIN)
				{
					continue;
				}
				else if (bytes < 0)
				{
					Throw("socket error",errno);
				}

				sent_bytes += bytes;
			}
		}
		else if( retval == 0 )
		{
			Throw("Socket time out", 0);
		}
		else
		{
			Throw("Select failed", errno);
		}
	}

	return;
}
예제 #4
0
/***********************************************************************
 *
 * FUNCTION:    SelectTime
 *
 * DESCRIPTION: Display a form showing a start and end time.
 *					 Allow the user to change the time and then
 *              return them.
 *					 pTimeDiff.
 *
 * PARAMETERS:  pStartTime	- pointer to TimeType
 *              pEndTime   - pointer to TimeType
 *              untimed  	- true if there isn't a time.
 *              title	   - string containing the title
 *              startOfDay - used when "All Day" button selected.
 *					 endOfDay	- our used when "All Day" button selected.
 *              startOfDisplay - first hour initially visible
 *
 * RETURNED:	 True if the time was changed by the user.
 * 				 The first three parameters may change.
 *
 * REVISION HISTORY:
 *			Name	Date		Description
 *			----	----		-----------
 *			roger	12/2/94	Initial Revision
 *			trev	08/12/97	made non modified passed variables constant
 *			css	06/08/99	added new parameter & "All Day" button for gromit change.
 *
 ***********************************************************************/
Boolean SelectTime (TimeType * startTimeP, TimeType * endTimeP, 
	Boolean untimed, const Char * titleP, Int16 startOfDay, Int16 endOfDay, 
	Int16 startOfDisplay)
{
	Int16							firstHour;
	Char 							startTimeText [timeStringLength];
	Char 							endTimeText [timeStringLength];
	Char							timeChars [timeStringLength];
	TimePtr						timeP;
	FormType 					*originalForm, *frm;
	ListPtr 						hoursLst, minutesLst;
	ControlPtr 					startTimeCtl, endTimeCtl;
	EventType 					event;
	Boolean 						confirmed = false;
	MemHandle 						hoursItems;
	TimeType 					startTime, endTime, timeDiff;
	TimeFormatType 			timeFormat;
	ChangingTimeType			changingTime;

	// Get the time format from the system preerances;
	timeFormat = (TimeFormatType)PrefGetPreference(prefTimeFormat);


	// Because this routine only deals with minutes in five minute
	// intervals we convert the proposed times from those passed.
	startTime.hours = startTimeP->hours;
	startTime.minutes = startTimeP->minutes;
	endTime.hours = endTimeP->hours;
	endTime.minutes = endTimeP->minutes;
	TimeDifference (&endTime, &startTime, &timeDiff);
	
	// Make sure the end time is displayable (clips at 11:55 pm)
	AdjustTimes (&startTime, &endTime, &timeDiff, changingStartTime);
	
	// Clear the buffer that holds written characters.
	*timeChars = 0;

	startOfDisplay = min (startOfDisplay, 12);

	originalForm = FrmGetActiveForm();
	frm = (FormType *) FrmInitForm (TimeSelectorForm);
	FrmSetActiveForm (frm);

	hoursLst = FrmGetObjectPtr (frm, FrmGetObjectIndex (frm, TimeSelectorHourList));
	minutesLst = FrmGetObjectPtr (frm, FrmGetObjectIndex (frm, TimeSelectorMinuteList));
	startTimeCtl = FrmGetObjectPtr (frm, FrmGetObjectIndex (frm, TimeSelectorStartTimeButton));
	endTimeCtl = FrmGetObjectPtr (frm, FrmGetObjectIndex (frm, TimeSelectorEndTimeButton));


	// Set list to use either 12 or 24 hour time
	hoursItems = SysFormPointerArrayToStrings (
		((timeFormat == tfColon24h) || (timeFormat == tfDot24h)) ? 
			(Char *) Hours24Array() : (Char *) Hours12Array(), 24);
 
 	LstSetListChoices (hoursLst, MemHandleLock(hoursItems), 24);
	LstSetTopItem (hoursLst, startOfDisplay);
	//	Used to do LstMakeItemVisible (hoursLst, startTime.hours); no longer.


	if (! untimed)
		{
		LstSetSelection (hoursLst, startTime.hours);
		LstSetSelection (minutesLst, startTime.minutes / 5);

		CtlSetValue (startTimeCtl, true);
		changingTime = changingStartTime;
		}
	else
		{
		// The hour list is dynamically created and doesn't have a selection
		LstSetSelection (minutesLst, noListSelection);

		changingTime = changingNoTime;
		}


	// Set the start and end time buttons to the current times or blank them
	// if No Time is selected.
	SetTimeTriggers (startTime, endTime, startTimeText, endTimeText, 
		timeFormat, untimed);
		

	// This needs to be taken out when SelectTimeV33 goes away.  It allows for backward 
	// compatibility for this change of adding the end of day variable as a parameter.
	if (endOfDay != noDisplayOfAllDay)
	{
	  FrmShowObject (frm, FrmGetObjectIndex (frm, TimeSelectorAllDayButton));
	}
	
	FrmSetTitle (frm, (Char *) titleP);
	FrmDrawForm (frm);
	
	
	while (true)
		{
		EvtGetEvent (&event, evtWaitForever);

		if (SysHandleEvent ((EventType *)&event))
			continue;
			
		if (event.eType == appStopEvent)
			{
			// Cancel the dialog and repost this event for the app
			EvtAddEventToQueue(&event);
			confirmed = false;
			break;
			}
			
		// Handle these before the form does to overide the default behavior
		if (changingTime == changingNoTime &&
			event.eType == lstEnterEvent && 
			event.data.lstEnter.listID == TimeSelectorMinuteList)
			{
			SndPlaySystemSound(sndError);
			continue;
			}

		FrmHandleEvent (frm, &event);


		// If the start or end time buttons are pressed then change
		// the time displayed in the lists.
		if (event.eType == ctlSelectEvent)
			{
			// "Ok" button pressed?
			if (event.data.ctlSelect.controlID == TimeSelectorOKButton)
				{
				confirmed = true;
				}

			// "Cancel" button pressed?
			else if (event.data.ctlSelect.controlID == TimeSelectorCancelButton)
				{
				break;
				}

			// Start time button pressed?
			else if (event.data.ctlSelect.controlID == TimeSelectorStartTimeButton)
				{
				if (changingTime != changingStartTime)
					{
					if (changingTime == changingNoTime)
						{
						SetTimeTriggers (startTime, endTime, startTimeText, 
							endTimeText, timeFormat, false);
						}

					CtlSetValue (endTimeCtl, false);
					LstSetSelection (hoursLst, startTime.hours);
					LstSetSelection (minutesLst, startTime.minutes / 5);
					changingTime = changingStartTime;
					}
				else
					CtlSetValue(startTimeCtl, true);
				}

			// End time button pressed?
			else if (event.data.ctlSelect.controlID == TimeSelectorEndTimeButton)
				{
				if (changingTime != changingEndTime)
					{
					if (changingTime == changingNoTime)
						{
						SetTimeTriggers (startTime, endTime, startTimeText, 
							endTimeText, timeFormat, false);
						}

					CtlSetValue(startTimeCtl, false);
					LstSetSelection (hoursLst, endTime.hours);
					LstSetSelection (minutesLst, endTime.minutes / 5);
					changingTime = changingEndTime;
					}
				else
					CtlSetValue(endTimeCtl, true);
				}

			// No time button pressed?
			else if (event.data.ctlSelect.controlID == TimeSelectorNoTimeButton)
				{
				if (changingTime != changingNoTime)
					{
					if (changingTime == changingStartTime)
						CtlSetValue(startTimeCtl, false);
					else
						CtlSetValue(endTimeCtl, false);
					SetTimeTriggers (startTime, endTime, startTimeText, 
						endTimeText, timeFormat, true);
					
					LstSetSelection (hoursLst, noListSelection);
					LstSetSelection (minutesLst, noListSelection);
					changingTime = changingNoTime;
					}
					// Get us out of this form display now.
					confirmed = true;
				}

			// All day button pressed?
			else if (event.data.ctlSelect.controlID == TimeSelectorAllDayButton)
				{
				if (changingTime != changingNoTime)
					{
					if (changingTime == changingStartTime)
						CtlSetValue(startTimeCtl, false);
					else
						CtlSetValue(endTimeCtl, false);
					
					LstSetSelection (hoursLst, noListSelection);
					LstSetSelection (minutesLst, noListSelection);
					changingTime = changingNoTime;
					}
											
					// No matter what, the minutes are 0 for both because only the hour is registered for start/end
					// times.
					startTime.minutes = 0;
					endTime.minutes 	= 0;
					startTime.hours 	= startOfDay;
					endTime.hours 		= endOfDay;
					
					// Set the times to the new times.
					SetTimeTriggers (startTime, endTime, startTimeText, 
						endTimeText, timeFormat, true);
					// Get us out of this form display now.  First set the changing time to anything but the changingNoTime value
					// so that the pointers at the end of this function get set correctly.
					changingTime = changingStartTime;
					confirmed = true;
				}

			// Clear the buffer that holds written characters.
			*timeChars = 0;
			}


		// If either list is changed then get the new time.  If the
		// start time is changed then change the end time so that the
		// the time difference remains the same.  If the end time is
		// changed then make sure the end time isn't before the start
		// time.  Also calculate a new time difference.
		else if (event.eType == lstSelectEvent)
			{
         // First, get the info from the list which has changed.
			if (event.data.lstSelect.listID == TimeSelectorHourList)
				{
				if (changingTime == changingStartTime)
               startTime.hours = (UInt8) LstGetSelection (hoursLst);
           	else if (changingTime == changingEndTime)
               endTime.hours = (UInt8) LstGetSelection (hoursLst);
           	else if (changingTime == changingNoTime)
           		{
               startTime.hours = (UInt8) LstGetSelection (hoursLst);
					SetTimeTriggers (startTime, endTime, startTimeText, 
						endTimeText, timeFormat, false);
					CtlSetValue (endTimeCtl, false);
					LstSetSelection (minutesLst, startTime.minutes / 5);
					changingTime = changingStartTime;
					}
				}
         else if (event.data.lstSelect.listID == TimeSelectorMinuteList)
				{
				if (changingTime == changingStartTime)
               startTime.minutes = (UInt8) LstGetSelection (minutesLst) * 5;
           	else if (changingTime == changingEndTime)
					endTime.minutes = (UInt8) LstGetSelection (minutesLst) * 5;
           	else if (changingTime == changingNoTime)
           		{
               ErrNonFatalDisplay("lstEnterEvent not being filtered.");
               }
				}


			if (AdjustTimes (&startTime, &endTime, &timeDiff, changingTime))
				{
				if (changingTime == changingStartTime)
					{
					TimeToAscii (startTime.hours, startTime.minutes, timeFormat, 
						startTimeText);
					CtlSetLabel (startTimeCtl, startTimeText);
					}
				else if (changingTime == changingEndTime)
					{
					LstSetSelection (hoursLst, startTime.hours);
					LstSetSelection (minutesLst, startTime.minutes / 5);
					}
				}
			TimeToAscii(endTime.hours, endTime.minutes, timeFormat, endTimeText);
			CtlSetLabel(endTimeCtl, endTimeText);


			// Clear the buffer that holds written characters.
			*timeChars = 0;
			}


		// Handle character written in the time picker.
		else if (event.eType == keyDownEvent)
			{
			if (changingTime == changingEndTime)
				{
				timeP = &endTime;
				firstHour = startTime.hours;
				}
			else
				{
				timeP = &startTime;
				firstHour = startOfDisplay;
				}
		
			// If a backspace character was written, change the time picker's
			// current setting to "no-time".
			if (event.data.keyDown.chr == backspaceChr)
				{
				*timeChars = 0;
				if (changingTime != changingNoTime)
					{
					if (changingTime == changingStartTime)
						CtlSetValue (startTimeCtl, false);
					else
						CtlSetValue (endTimeCtl, false);
					SetTimeTriggers (startTime, endTime, startTimeText, 
						endTimeText, timeFormat, true);
					LstSetSelection (hoursLst, noListSelection);
					LstSetSelection (minutesLst, noListSelection);
					changingTime = changingNoTime;
					}
				}

			// A linefeed character confirms the dialog box.
			else if (event.data.keyDown.chr == linefeedChr)
				{
				confirmed = true;
				}

			// If next-field character toggle between start time in end
			// time.
			else if (event.data.keyDown.chr == nextFieldChr)
				{
				*timeChars = 0;
				if (changingTime == changingStartTime)
					{
					CtlSetValue (startTimeCtl, false);
					CtlSetValue (endTimeCtl, true);
					changingTime = changingEndTime;
					}
				else
					{
					CtlSetValue (endTimeCtl, false);
					CtlSetValue (startTimeCtl, true);
					changingTime = changingStartTime;
					}
				}


			// If a valid time character was written, translate the written 
			// character into a time and update the time picker's UI.
			else if (TranslateTime (timeFormat, event.data.keyDown.chr, 
				firstHour, timeChars, timeP))
				{
				if (changingTime == changingNoTime)
					{
					changingTime = changingStartTime;
					CtlSetValue (startTimeCtl, true);
					}

				AdjustTimes (&startTime, &endTime, &timeDiff, changingTime);
				
				SetTimeTriggers (startTime, endTime, startTimeText, 
					endTimeText, timeFormat, false);

				LstSetSelection (hoursLst, timeP->hours);
				LstSetSelection (minutesLst, timeP->minutes / 5);
				}
			}

		// Has the dialog been confirmed.
		if (confirmed)
			{
			if (changingTime != changingNoTime)
				{
				*startTimeP = startTime;
				*endTimeP = endTime;
				}
			else
				{
				TimeToInt(*startTimeP) = noTime;
				TimeToInt(*endTimeP) = noTime;
				}
			break;
			}

		}

	FrmEraseForm (frm);
	FrmDeleteForm (frm);
	MemHandleFree (hoursItems);
	
	FrmSetActiveForm(originalForm);
	
	return (confirmed);
	}
예제 #5
0
int SslClient:: RecvCLRF(std::string& str_, long timeout_)
{
    char buf[2];
    std::string::size_type pos_clrf;

    int retval;
    fd_set read_fds;
    fd_set write_fds;
    struct timeval timeout;
    struct timeval *ptimeout;

    str_ = "";
    buf[1] = '\0';

    // 如果将缓冲区设置为一个较大值
    // 则有可能导致当前读取的数据越过第一个CLRF符,读取到多余的数据
    // 在这种情况下,如果要使程序正常运行,则需要开辟全局的存储空间,存储CLRF后的数据
    // 这将导致前后两个RecvCLRF调用失去独立性,增加编程的复杂度
    // 权衡效率与复杂度,选择牺牲效率
    while(1)
    {
        FD_ZERO(&read_fds);
        FD_ZERO(&write_fds);

        bool need_io;
        do
        {
            need_io = false;

            int bytes;
            bytes = SSL_read(this->ssl_m, buf, 1);

            switch(SSL_get_error(ssl_m, bytes))
            {
            case SSL_ERROR_NONE:
                // 没有错误,把这个字节加到目标字符串上
                str_ += buf;
                break;

            case SSL_ERROR_ZERO_RETURN:
                Throw("socket closed by client", 0);
                break;

            case SSL_ERROR_WANT_READ:
#ifdef SslClient_DEBUG
                printf("SSL_ERROR_WANT_READ\n");
#endif
                FD_SET(this->sock_fd, &read_fds);

                need_io = true;
                break;

            case SSL_ERROR_WANT_WRITE:
#ifdef SslClient_DEBUG
                printf("SSL_ERROR_WANT_WRITE\n");
#endif
                FD_SET(this->sock_fd, &write_fds);

                need_io = true;
                break;

            case SSL_ERROR_SYSCALL:
                Throw("ssl I/O error occurred", MException::ME_RUNTIME);
                break;

            default:
                Throw("SSL_read() failed", MException::ME_RUNTIME);
            }

            // 测试是否读取到了CLRF
            if( (pos_clrf = str_.find("\r\n")) == std::string::npos )
            {
                // 没有,继续
                continue;
            }
            else
            {
                // 有,赋给传入参数
                str_.erase(pos_clrf);
            }

        } while(need_io == false && pos_clrf == std::string::npos);

        // 跳出外层循环
        if(pos_clrf != std::string::npos)
        {
            break;
        }

        ptimeout= TranslateTime(timeout_, &timeout);

        while((retval = select(FD_SETSIZE, &read_fds, &write_fds, NULL, ptimeout)) == -1
                && errno == EINTR);

        if(retval > 0)
        {
            continue;
        }
        else if(retval == 0)
        {
            Throw("Socket timeout",0);
        }
        else
        {
            Throw("Select on socket failed", errno);
        }
    }

    return 0;
}
예제 #6
0
void SslClient:: CSend(const void *buf_, size_t length_, long timeout_)
{
    int retval;
    fd_set write_fds;
    fd_set read_fds;
    size_t sent_bytes = 0;
    struct timeval timeout;
    struct timeval* ptimeout;

    do
    {
        FD_ZERO(&write_fds);
        FD_ZERO(&read_fds);

        bool need_io;

        do
        {
            int bytes;
            need_io = false;

            bytes = SSL_write(this->ssl_m, (char *)buf_ + sent_bytes, length_ - sent_bytes);

            if(bytes > 0)
            {
                sent_bytes += bytes;
                continue;
            }

            // 测试错误
            switch(SSL_get_error(ssl_m, bytes))
            {
            case SSL_ERROR_NONE:
                break;

            case SSL_ERROR_ZERO_RETURN:
                Throw("socket closed by client", 0);
                break;

            case SSL_ERROR_WANT_READ:
#ifdef SslClient_DEBUG
                printf("SSL_ERROR_WANT_READ\n");
#endif
                FD_SET(this->sock_fd, &read_fds);

                need_io = true;
                break;

            case SSL_ERROR_WANT_WRITE:
#ifdef SslClient_DEBUG
                printf("SSL_ERROR_WANT_WRITE\n");
#endif
                FD_SET(this->sock_fd, &write_fds);

                need_io = true;
                break;

            case SSL_ERROR_SYSCALL:
                Throw("ssl I/O error occurred", MException::ME_RUNTIME);
                break;

            default:
                Throw("SSL_read() failed", MException::ME_RUNTIME);

            }

        } while(need_io == false && sent_bytes != length_);

        if( sent_bytes == length_ )
        {
            break;
        }

        ptimeout= TranslateTime(timeout_, &timeout);

        // 等待数据到来
        while((retval = select(FD_SETSIZE, &read_fds, &write_fds, NULL, ptimeout)) == -1
                && errno == EINTR);

        if( retval > 0 )
        {
            continue;
        }
        else if( retval == 0 )
        {
            Throw("Socket time out", 0);
        }
        else
        {
            Throw("Select failed", errno);
        }

    } while(sent_bytes != length_);

    return;
}
예제 #7
0
int SslClient:: Recv(void *buf_, size_t length_, long timeout_)
{
    int retval;
    int bytes;
    fd_set read_fds;
    fd_set write_fds;
    struct timeval timeout;
    struct timeval* ptimeout;

    // 由于ssl在用户与内核之间保留了一块缓冲区存放数据
    // 如果一开始就进行select,有可能遇到这样的情况:
    //  1、上一次调用后,ssl缓冲区内的数据还没有读完
    //  2、对方主机的数据已经发送完毕
    // 这时在SSL_read之前使用select,将会导致当前线程始终阻塞
    // 导致程序僵死
    while(1)
    {
        FD_ZERO(&read_fds);
        FD_ZERO(&write_fds);

        bool need_io;
        bool shutdown;

        do
        {
            need_io = false;
            shutdown = false;

            // 读取数据
            if( ( bytes = SSL_read(this->ssl_m, (char *)buf_, length_) ) > 0)
            {
                break;
            }

            // 检查错误
            switch(SSL_get_error(ssl_m, bytes))
            {
            case SSL_ERROR_NONE:
                break;

            case SSL_ERROR_ZERO_RETURN:
                bytes = 0;
                shutdown = true;
                break;

            // ssl缓冲区已经为空,需要读取数据
            case SSL_ERROR_WANT_READ:
#ifdef SslClient_DEBUG
                printf("SSL_ERROR_WANT_READ\n");
#endif
                FD_SET(this->sock_fd, &read_fds);
                need_io = true;
                break;

            // 需要写数据
            // 注意:即使是SSL_read,也可能返回SSL_ERROR_WANT_WRITE
            // 因为ssl中涉及到一些握手与校验信息,通信始终是双向的
            // 所以不光要设置读套接字集(read_fds),还要设置写套接字集(write_fds)
            case SSL_ERROR_WANT_WRITE:
#ifdef SslClient_DEBUG
                printf("SSL_ERROR_WANT_WRITE\n");
#endif
                FD_SET(this->sock_fd, &write_fds);
                need_io = true;
                break;

            case SSL_ERROR_SYSCALL:
                Throw("ssl I/O error occurred", MException::ME_RUNTIME);
                break;

            default:
                Throw("SSL_read() failed", MException::ME_RUNTIME);
            }

        } while(need_io == false && shutdown == false);

        // 跳出最外层的循环
        if(bytes >= 0)
        {
            break;
        }

        ptimeout= TranslateTime(timeout_, &timeout);

        while((retval = select(FD_SETSIZE, &read_fds, &write_fds, NULL, ptimeout)) == -1
                && errno == EINTR);

        if ( retval > 0 )
        {
            // FIXME
            // 这里是否要调用FD_ISSET(this->sock_fd, &read_fds) ?
            continue;
        }
        else if( retval == 0 )
        {
            Throw("Socket time out", 0);
        }
        else
        {
            Throw("Select failed", errno);
        }
    }

    return bytes;
}
예제 #8
0
int TcpClient::Recv(char *buf_, size_t length_, long timeout_)
{
	int retval;
	int bytes;
	fd_set read_fds;
	struct timeval timeout;
	struct timeval* ptimeout;
	
	while(1)
	{
		FD_ZERO(&read_fds);
		FD_SET(this->sock_fd, &read_fds);

		ptimeout = TranslateTime(timeout_, &timeout);

		// 等待数据到来
/*		
		while((retval = select(FD_SETSIZE, &read_fds, NULL, NULL, ptimeout)) == -1 
				&& errno == EINTR);
		// xian add 2011-9-26 15:16:23 由 FD_SETSIZE ==> this->sock_fd + 1
*/		
		while((retval = select(this->sock_fd + 1, &read_fds, NULL, NULL, ptimeout)) == -1 
				&& errno == EINTR);

		// select 成功返回
		if ( retval > 0 )
		{
			if (FD_ISSET(this->sock_fd, &read_fds))
			{
				// 接收数据
				while( (bytes = recv(this->sock_fd, buf_, length_, MSG_DONTWAIT)) == -1 
						&& errno == EINTR); 

				// 套接字有可能在select返回到recv读取的这段时间内又不可用
				// 重新回去等待
				// FIXME 是否会导致忙等?
				if(bytes == -1 && errno == EAGAIN)
				{
					continue;
				}	
				else if (bytes == 0) // 连接被关闭
				{
					break;
				}
				else if (bytes < 0)
				{
					Throw("Socket error",errno);
				}
				else
				{
					break;
				}
			}
		}
		else if( retval == 0 )
		{
			Throw("Socket time out", 0);
		}
		else
		{
			Throw("Select failed", errno);
		}
	}

	return bytes;
}
예제 #9
0
int TcpClient::RecvCLRF(std::string& str_, long timeout_)
{
	char buf[BUFSIZE + 1];
	std::string::size_type pos_clrf;

	fd_set read_fds;
	int retval;
	struct timeval timeout;
	struct timeval *ptimeout;

	str_.clear();
//	buf[1] = '\0';

	while(1)
	{
		FD_ZERO(&read_fds);
		FD_SET(this->sock_fd, &read_fds);

		ptimeout= TranslateTime(timeout_, &timeout);

		// 等待套接字可读
		while((retval = select(this->sock_fd + 1, &read_fds, NULL, NULL, ptimeout)) == -1 
				&& errno == EINTR);

		if(retval > 0)
		{
			if (FD_ISSET(this->sock_fd, &read_fds))
			{

				int bytes;
				while( (bytes = recv(this->sock_fd, buf, BUFSIZE, MSG_DONTWAIT)) == -1 
						&& errno == EINTR);

				if( bytes == -1 && errno == EAGAIN)
				{
					continue;
				}
				else if (bytes == 0)
				{
					Throw("socket closed by client", 0);
				}
				else if(bytes < 0)
				{
					Throw("recv data failed", errno);
				}

				buf[bytes] = 0;
				str_ += buf;

				// 如果没有clrf字符串,继续读取
				if( (pos_clrf = str_.find("\r\n")) == std::string::npos )
				{
					continue;
				}
				else // 找到clrf字符串,提取并跳出循环
				{
					str_.erase(pos_clrf);
					break;
				}
			}
		}
		else if(retval == 0)
		{
			Throw("Socket timeout",0);
		}
		else
		{
			Throw("Select failed", errno);
		}
	}

	return 0;
}
예제 #10
0
void CWorldSocket::OnClose(int nErrorCode)
  {

bool bWasClosed = m_pDoc->m_iConnectPhase == eConnectNotConnected;

  TRACE1 ("CWorldSocket::OnClose, error code %i\n", nErrorCode);

  m_pDoc->m_iConnectPhase = eConnectDisconnecting;

  m_pDoc->UpdateAllViews (NULL);

  m_pDoc->MXP_Off (true);   // turn off MXP now

  // update button bar - make button red
  if (m_pDoc->m_view_number >= 1 &&
      m_pDoc->m_view_number <= 10)
    Frame.OnUpdateBtnWorlds (m_pDoc->m_view_number, NULL);

  // execute "disconnect" script
  if (m_pDoc->m_ScriptEngine)
    {
    if (m_pDoc->SeeIfHandlerCanExecute (m_pDoc->m_strWorldDisconnect))
      {
      DISPPARAMS params = { NULL, NULL, 0, 0 };
      long nInvocationCount = 0;

      m_pDoc->ExecuteScript (m_pDoc->m_dispidWorldDisconnect,  
                             m_pDoc->m_strWorldDisconnect,
                             eWorldAction,
                             "world disconnect", 
                             "disconnecting from world",
                             params, 
                             nInvocationCount); 
      }
    } // end of executing disconnect script

  m_pDoc->SendToAllPluginCallbacks (ON_PLUGIN_DISCONNECT);

  // close log file if we auto-opened it
  if (!m_pDoc->m_strAutoLogFileName.IsEmpty ())
    m_pDoc->CloseLog ();

  if (m_pDoc->m_bShowConnectDisconnect && !bWasClosed)
    {
    CTime theTime;
    theTime = CTime::GetCurrentTime();

    CString strConnected;
    strConnected = theTime.Format (TranslateTime ("--- Disconnected on %A, %B %d, %Y, %#I:%M %p ---"));

    m_pDoc->Note (strConnected);  

    // find time spent connected
    CTimeSpan ts = CTime::GetCurrentTime() - m_pDoc->m_tConnectTime;
      
    CString strDuration = TFormat ("--- Connected for %i day%s, %i hour%s, %i minute%s, %i second%s. ---",
                  PLURAL ((long) ts.GetDays()),
                  PLURAL ((long) ts.GetHours()),
                  PLURAL ((long) ts.GetMinutes()),
                  PLURAL ((long) ts.GetSeconds()));

    m_pDoc->Note (strDuration);  

    // and a horizontal rule

    m_pDoc->m_pCurrentLine->flags = HORIZ_RULE;  
    m_pDoc->StartNewLine (true, 0); 
    }  // end of message in world window wanted

  CString strInfo = TFormat ("--- Received %i line%s, sent %i line%s.",
                PLURAL (m_pDoc->m_nTotalLinesReceived),
                PLURAL (m_pDoc->m_nTotalLinesSent)
                );
  
  m_pDoc->Note (strInfo);  

  strInfo = TFormat ("--- Output buffer has %i/%i line%s in it (%.1f%% full).",
                m_pDoc->m_LineList.GetCount (),
                m_pDoc->m_maxlines,
                (m_pDoc->m_LineList.GetCount ()) == 1 ? "" : "s",
                (double) m_pDoc->m_LineList.GetCount () / (double) m_pDoc->m_maxlines * 100.0
                );

  m_pDoc->Note (strInfo);  

  strInfo = TFormat ("--- Matched %i trigger%s, %i alias%s, and %i timer%s fired.",
                PLURAL (m_pDoc->m_iTriggersMatchedThisSessionCount),   
                PLURALES (m_pDoc->m_iAliasesMatchedThisSessionCount),    
                PLURAL (m_pDoc->m_iTimersFiredThisSessionCount)       
                );

  m_pDoc->Note (strInfo);  

CString str;

  str = TFormat ("The \"%s\" server has closed the connection", 
              (const char *) m_pDoc->m_mush_name);

  if (App.m_bNotifyOnDisconnect && !m_pDoc->m_bDisconnectOK)
    {
    if (App.m_bErrorNotificationToOutputWindow)
      m_pDoc->Note (str);
    else
      ::UMessageBox (str, MB_ICONEXCLAMATION);
    }
  else
    Frame.SetStatusMessage (str);
  m_pDoc->m_iConnectPhase = eConnectNotConnected;

  m_pDoc->UpdateAllViews  (NULL);     // force window title to be redrawn

  } // end of OnClose