C++ 之Socket 程式設計 send rev 阻塞設定 阻塞超時時間

feiyang094發表於2015-07-23

int nTimeout,=1000;

set

//設定傳送超時為1000ms
if( SOCKET_ERROR == setsockopt( sockClient, SOL_SOCKET, SO_SNDTIMEO,
                               (char *)&nTimeout, sizeof( int ) ) )
{
fprintf( stderr, "Set SO_SNDTIMEO error !\n" );
}
//設定接收超時為1000ms
if( SOCKET_ERROR == setsockopt( sockClient, SOL_SOCKET, SO_RCVTIMEO,
                               (char *)&nTimeout, sizeof( int ) ) )
{
fprintf( stderr, "Set SO_RCVTIMEO error !\n" );
}


注意:

1、rev() 的第四個引數 需要設為 MSG_WAITALL,一直阻塞,知道指定數目的資料到來才返回,除非超時時間到達。如果,設定了接收超時,在沒有MSG_WAITALL,情況下,也是有效的,

2.即使等待超時時間值未到,對方關閉了socket()。rev()會立即返回接收到的資料位元組。


#include <WINSOCK2.H>
#include <stdio.h>
#pragma comment(lib,"ws2_32.lib")
int main(int argc,char **argv)
{
    //建立套接字
    WORD myVersionRequest;
    WSADATA wsaData;
    myVersionRequest=MAKEWORD(1,1);
    int err;
    err=WSAStartup(myVersionRequest,&wsaData);
    if (!err){
        printf("已開啟套接字\n");
    }else{
        printf("ERROR:巢狀字未開啟!");
        return 1;
    }
    //進一步繫結套接字
    SOCKET serSocket=socket(AF_INET,SOCK_STREAM,0);//建立了可識別套接字

    //需要繫結的引數
    SOCKADDR_IN addr;
    addr.sin_family=AF_INET;
    addr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//ip地址
    addr.sin_port=htons(6000);//繫結埠

    bind(serSocket,(SOCKADDR*)&addr,sizeof(SOCKADDR));//繫結完成
    listen(serSocket,5);//其中第二個引數代表能夠接收的最多的連線數

    //////////////////////////////////////////////////////////////////////////
    //開始進行監聽
    //////////////////////////////////////////////////////////////////////////
    SOCKADDR_IN clientsocket;
    int len=sizeof(SOCKADDR);
    while (1)
    {
        SOCKET serConn=accept(serSocket,(SOCKADDR*)&clientsocket,&len);//如果這裡不是accept而是conection的話。。就會不斷的監聽
        char sendBuf[100];

        sprintf(sendBuf,"hello, %s !",inet_ntoa(clientsocket.sin_addr));//找對對應的IP並且將這行字列印到那裡
        printf("Send:%s\n",sendBuf);
        send(serConn,sendBuf,strlen(sendBuf)+1,0);

        char receiveBuf[100];//接收
        recv(serConn,receiveBuf,sizeof(receiveBuf),0);
        printf("recv:%s\n",receiveBuf);

        closesocket(serConn);//關閉
        WSACleanup();//釋放資源的操作
        return 0;
    }
    return 1;
}

Client 

bool CTcpSocket::Connect()
{
//SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);
sockClient = socket( AF_INET, SOCK_STREAM, 0 );
SOCKADDR_IN addrSrv;
//addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
addrSrv.sin_addr.S_un.S_addr   = inet_addr(m_server.c_str());
addrSrv.sin_family   = AF_INET;
addrSrv.sin_port   = htons( m_port );


int nTimeout = TCP_TIME_MAX;
//設定傳送超時為1000ms
if( SOCKET_ERROR == setsockopt( sockClient, SOL_SOCKET, SO_SNDTIMEO,
                               (char *)&nTimeout, sizeof( int ) ) )
{
fprintf( stderr, "Set SO_SNDTIMEO error !\n" );
}
//設定接收超時為1000ms
if( SOCKET_ERROR == setsockopt( sockClient, SOL_SOCKET, SO_RCVTIMEO,
                               (char *)&nTimeout, sizeof( int ) ) )
{
fprintf( stderr, "Set SO_RCVTIMEO error !\n" );
}


if( connect( sockClient, (SOCKADDR*)&addrSrv, sizeof( SOCKADDR ) ) == 0 )
{
 // CLOG::Out0( L"DEBUG", L"%d.client connect:%s,%d" ,sockClient,CComon::ToCString( inet_ntoa(addrSrv.sin_addr)),ntohs(addrSrv.sin_port));  
return true;
} else
{
return false;
}


//true;
}


接收開闢一個執行緒

 /**
 * @brief  Receive datas from severs.
 * @note
 * @param
 * @retval None
 */
int CTcpSocket::Receive( __out_bcount_part(len, return ) __out_data_source(NETWORK) char FAR * buf,
                            __in int len )
{
int re = recv( sockClient, buf, len, 0 );
return re;
}

/**
 * @brief  Receive datas from severs.
 * @note
 * @param
 * @retval None
 */
UINT SocketReceivePross(void *pagram)
{
    CTcpSocket *temp=  (CTcpSocket*) pagram;
while (1)
{
memset(temp->dataBuf,0,BUF_SZIE);
  int length= temp->Receive(temp->dataBuf, sizeof(temp->dataBuf)); //阻塞等待5S
if ( length>0)
{
temp->Analysis();
}
  ::Sleep(1); 
}
}

相關文章