TCP编程的流程

TCP流程

 

1、检查版本号——  

// Init WinSock

     WSADATA   data;

     int ret = WSAStartup(0x0202, &data);

     if (ret != 0)

     {

         WSACleanup();

         return FALSE;

     }

2、建立套接字,绑定,监听——

     mListener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

     if (mListener != INVALID_SOCKET)

     {

         // Settings on socket

         BOOL  sopt = TRUE;

         setsockopt(mListener, IPPROTO_TCP, TCP_NODELAY,

              (char *)&sopt, sizeof(BOOL));

         setsockopt(mListener, SOL_SOCKET, SO_DONTLINGER,

              (char *)&sopt, sizeof(BOOL));

 

         // Bind socket and listen

         SOCKADDR_IN  addr;

         memset(&addr, 0, sizeof(SOCKADDR_IN));

         addr.sin_family      = AF_INET;

         addr.sin_addr.s_addr = htonl(INADDR_ANY);

          addr.sin_port        = htons(mListenPort);

         val = bind(mListener, (struct sockaddr*) &addr, sizeof(addr));

         pass = (val != SOCKET_ERROR);

     }

 

     if (pass)

     {

         // Put the socket into the listening status

         val = listen(mListener, SOMAXCONN);

         pass = (val != SOCKET_ERROR);

     }

 

SOCKET socket( IN int af, IN int type, IN int protocol );

af (AF_INET) ARPA因特网协议(UNIX网络套接字);

type——SOCK_STREAM 流式套接字TCP;SOCK_DGRAM 数据报套接字UCP

protocol——0为默认值,IPPROTO_TCP IP网的TCP协议

 

int setsockopt(IN SOCKET s, IN int level, IN int optname, IN const char FAR * optval, IN int optlen);

——设置套接口的选项

// TCP_NODELAY选项禁止Nagle算法

//SO_DONTLINER BOOL 不要因为数据未发送就阻塞关闭操作。相当于将SO_LINGER的 l_onoff 元素置为零

 

int bind(IN SOCKET s,IN const struct sockaddr FAR * name,IN int namelen);

——绑定socket和地址和端口监听因特网上的任意ip地址接入 INADDR_ANY

 

int listen( IN SOCKET s,IN int backlog);

——backlog队列中可以容纳的未处理连接的最大数目限制

——listen函数为服务器程序创建一个队列来保存未处理的请求

 

3、接收连接

         DWORD threadID = 0;

         mLsnThread = CreateThread(NULL, 0, ListeningThrd,

              this, 0, &threadID);

 

//______________________ListenThrd 函数_______________________________

         SOCKET accepted = accept(mListener, (SOCKADDR *)&saddr, &len);

         if (accepted == INVALID_SOCKET)

         {

              return FALSE;

         }

        

         DeleteAccepted();

         mAccepted = accepted;

         // Settings on socket

         BOOL sopt = TRUE;

         setsockopt(mAccepted, IPPROTO_TCP, TCP_NODELAY,

              (char *)&sopt, sizeof(BOOL));

         setsockopt(mAccepted, SOL_SOCKET, SO_DONTLINGER,

              (char *)&sopt, sizeof(BOOL));

 

SOCKET accept(IN SOCKET s,OUT struct sockaddr FAR * addr,IN OUT int FAR * addrlen);

——accept系统调用只有当客户程序试图连接到由socket参数指定的套接字时才返回,即是说,accept将阻塞知道有客户建立连接为止。通常的做法是开一条新的线程。

——accept 返回新的套接字accepted。

 

4、客户端请求连接

     mSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

     if (mSocket != INVALID_SOCKET)

     {

         BOOL sopt = TRUE;

         setsockopt(mSocket, IPPROTO_TCP, TCP_NODELAY,

              (char *)&sopt, sizeof(BOOL));

         setsockopt(mSocket, SOL_SOCKET, SO_DONTLINGER,

              (char *)&sopt, sizeof(BOOL));

 

         SOCKADDR_IN   saddr;

         memset(&saddr, 0, sizeof(SOCKADDR_IN));

         saddr.sin_addr.S_un.S_addr = inet_addr(inTarget);

         saddr.sin_family           = AF_INET;

         saddr.sin_port             = htons((WORD)inPort);

         if (connect(mSocket, (SOCKADDR *)&saddr, sizeof(SOCKADDR_IN)) != 0){

}

}

 

int connect(IN SOCKET s,IN const struct sockaddr FAR * name,IN int namelen);

——客户程序通过在一个未命名套接字和服务器监听套接字之间建立连接的方法来连接到服务器。

——inTarget为服务器端ip地址。

——如果连接不能立刻建立,connect调用将阻塞一段不确定的超时时间。connect调用是阻塞的。

 

5、发送/接收数据

//__recv___

DWORD threadID = 0;

         mRcvThread = CreateThread(NULL, 0, ReceivingThrd,

              this, 0, &threadID);

//_________________________ReceivingThrd 函数____________________________________

     while (mIsReceiving)

     {

         bytes = recv(mSocket, buf, sizeof(Net_Header), 0);

         if (bytes == SOCKET_ERROR || bytes == 0)

         {

              Detach();

              mIsReceiving = FALSE;

              break;

         }

 

         pHeader->my_ntoh();

         bytes = recv(mSocket, buf, pHeader->pack_size, 0);

         if (bytes == SOCKET_ERROR || bytes == 0)

         {

              Detach();

              mIsReceiving = FALSE;

              break;

         }       

         buf[bytes]  = '\0';

     }

 

//__send___

         DWORD threadID = 0;

         mSndThread = CreateThread(NULL, 0, SendingThrd,

              this, 0, &threadID);

//_________________________ SendingThrd函数____________________________________

     char   str[] = "hello world!";

     int    len   = strlen(str) + sizeof(Net_Header);   

    

     Net_Header * pHeader = (Net_Header *) buf;

     pHeader->pack_size   = strlen(str);

     pHeader->my_hton();

     strcpy(buf+sizeof(Net_Header), str);

 

     bytes = send(mSocket, buf, len, 0);

     }

 

 

int recv( IN SOCKET s, OUT char FAR * buf, IN int len, IN int flags );

int send( IN SOCKET s, IN const char FAR * buf, IN int len, IN int flags );

——开新线程来发送和接收数据

 

6、关闭socket连接

     if (mSocket != INVALID_SOCKET)

     {

         closesocket(mSocket);

         mSocket = INVALID_SOCKET;

         mIsConnected = FALSE;

     }

 

7、关闭发送接收数据线程

     if (mIsReceiving)

     {

         Detach();

         if (mRcvThread != NULL)

         {

              WaitForSingleObject(mRcvThread, INFINITE);

              mRcvThread = NULL;

         }

     }

//__________

     if (mIsReceiving)

     {

         Detach();

         if (mRcvThread != NULL)

         {

              WaitForSingleObject(mRcvThread, INFINITE);

              mRcvThread = NULL;

         }

     }

 

——listen同样需要关闭socket和监听线程

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值