コンピュータネットワークシステム学習エッセンス総括(三):伝送層--4(ソケットプログラミング実戦、全二重通信)


フルデュプレクス通信.本文は前文の単双共通信モードの下で(接続:コンピュータネットワークシステム学習精華総括(三):伝送層--3(ソケットプログラミング実戦、半二重通信))、簡単なマルチスレッドプログラミングを採用して実現し、コードはほとんどの文に注釈を含む.
サービス側コード:
       
#include 
#include
#include //WSAADATA    
#include
#pragma comment (lib, "ws2_32.lib")
#pragma warning(disable : 4996)

/*     ,    */

//---------------   -----------------------
const int bufLen = 1024;
char reciveBuf[bufLen];    //      ,    
char sendBuf[bufLen];      //      
//---------------   -----------------------
using namespace std;

WSAEVENT bExit = WSACreateEvent();//           


//      
DWORD WINAPI recvMessage(LPVOID parsock)
{
	SOCKET recvsock = (SOCKET) parsock;        //           
	int err;                                   //    
	while (true)
	{
		memset(reciveBuf,0,sizeof(reciveBuf));//       
		if (recv(recvsock, reciveBuf, bufLen, 0) != SOCKET_ERROR)
		{//    
			cout << "    :" << reciveBuf << endl;
			if (strcmp(reciveBuf, "bye") == 0)
			{//       ,  bye
				SetEvent(bExit);//    ,    ,       
				break;
			}
		}
		else
		{//   
			err = WSAGetLastError();
			if (err == WSAECONNRESET)
			{//      
				cout << "The peer is closed" << endl;
				continue;//     
			}
			SetEvent(bExit);//f            
			break;
		}
	}
	closesocket(recvsock);//     
	WSACleanup();//    
	return 0;
}


//      
DWORD WINAPI sendMessage(LPVOID parsock)
{
	SOCKET sendsock = (SOCKET)parsock;        //           
	while (true)
	{
		cout << "         :" << endl;
		cin.getline(sendBuf, sizeof(sendBuf));
		send(sendsock, sendBuf, sizeof(sendBuf),0);//    
		if (strcmp(sendBuf, "bye") == 0)
		{
			SetEvent(bExit);//    
			break;
		}
	}
	closesocket(sendsock);	
	WSACleanup();//    
	return 0;
}

int main()
{
	//         ,  socket2.0  ,
	WSADATA wsaDATA;
	//WSAStartup(MAKEWORD(2, 0), &wsaDATA);
	if (WSAStartup(MAKEWORD(2, 0), &wsaDATA) != 0)
	{//     
		std::cout << "     " << std::endl;
		return -1;
	}

	//     ,int socket(int domain,int type,int protocol)
	/*socket       ——   (   、   ):               。AF_INET  TCP/IPv4,AF_INET6  TCP/IPv6,AF_LOCAL  AF_UNIX     ,             ,         
	socket       ——  :socket     ,SOCK_STREAM: TCP,     ,     ,    ,   ,     ,     。
	SOCK_DGRAM: UDP,     ,   ,   ,     ,     
	SOCK_RAW: IP,      ,   ,            ,     。
	socket       ——  :    , 0         ,IPPROTO_TCP\IPPTOTO_UDP\IPPROTO_SCTP\IPPROTO_TIPC,
	  type protocol      

	*/
	SOCKET  serverSocket = socket(AF_INET, SOCK_STREAM, 0);//     ,  ipv4,TCP  
	if (serverSocket == INVALID_SOCKET)
	{
		std::cout << "socket    " << std::endl;
		WSACleanup();//       
		return -1;
	}
	//     
	struct sockaddr_in  sockAddr;//         socket         ,struct sockaddr_in/sockaddr_in/SOCKADDR_IN
	sockAddr.sin_family = AF_INET;//   (   )
	sockAddr.sin_port = htons(8888);//      ,            
	sockAddr.sin_addr.s_addr = inet_addr("192.168.0.103");//inet_addr       IP               ,127.0.0.1       
														  //  s_addr    S_un.S_addr
														  //sockAddr.sin_addr.S_un.S_addr= inet_addr("127.0.0.1");

	int ret = bind(serverSocket, (struct sockaddr*)&sockAddr, sizeof(SOCKADDR_IN));//LPSOCKADDR   struct sockaddr*、SOCKADDR*
																				   //int bind(int sockfd,const struct socketaddr * addr,
	if (ret == SOCKET_ERROR)//
	{
		std::cout << "    !" << std::endl;
		WSACleanup();//       
		closesocket(serverSocket);//     
		return -1;
	}


	//      
	listen(serverSocket, 5);//5            
	if (listen(serverSocket, 5) < 0)//listen  0     ,  -1      
	{
		std::cout << "    !" << std::endl;
		WSACleanup();//       
		closesocket(serverSocket);//     
		return -1;

	}

	//       
	//SOCKADDR clsocket;
	SOCKADDR  clsocket;
	int len = sizeof(SOCKADDR);
	SOCKET newSock = accept(serverSocket, (SOCKADDR*)&clsocket, &len);
	if (newSock == SOCKET_ERROR)
	{
		std::cout << "   ——       !" << std::endl;
		return -1;
	}
	std::cout << "   ——       " << std::endl;

	//    ,       
	HANDLE send_thread, recv_thread;//         ,      
	DWORD nSthread, nRthread;    //       ID 
	/*  CreateThread()    
	                 
	                ,0    1MB
	                  
	                   ,             
	              ,         ,0             ,CREAT——SUSPENDED         ,    ResumeThread()  
	               
	*/
	send_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)sendMessage, (LPVOID)newSock, 0, &nSthread);//    
	recv_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)recvMessage, (LPVOID)newSock, 0, &nRthread);//    
	/*               ,  bExit     ( SetEvent()         )
	          
	*/
	WaitForSingleObject(bExit, INFINITE);
	closesocket(newSock);
	closesocket(serverSocket);
	WSACleanup();
	return 0;
}

クライアントコード:
         
#include 
#include
#include 
#pragma comment (lib, "ws2_32.lib")
#pragma warning(disable : 4996)
using namespace std;

/*     */

//---------------   -----------------------
const int bufLen = 1024;
char reciveBuf[bufLen];//    
char sendBuf[bufLen];//      
//---------------   -----------------------

WSAEVENT bExit = WSACreateEvent();//           

								  //      
DWORD WINAPI recvMessage(LPVOID parsock)
{
	SOCKET recvsock = (SOCKET)parsock;        //           
	int err;                                   //    
	while (true)
	{
		memset(reciveBuf, 0, sizeof(reciveBuf));//       
		if (recv(recvsock, reciveBuf, bufLen, 0) != SOCKET_ERROR)
		{//    
			cout << "    :" << reciveBuf << endl;
			if (strcmp(reciveBuf, "bye") == 0)
			{//       ,  bye
				SetEvent(bExit);//    ,    ,       
				break;
			}
		}
		else
		{//   
			err = WSAGetLastError();
			if (err == WSAECONNRESET)
			{//      
				cout << "The peer is closed" << endl;
				continue;//     
			}
			SetEvent(bExit);//f            
			break;
		}
	}
	closesocket(recvsock);//     
	WSACleanup();//    
	return 0;
}


//      
DWORD WINAPI sendMessage(LPVOID parsock)
{
	SOCKET sendsock = (SOCKET)parsock;        //           
	while (true)
	{
		cout << "         :" << endl;
		cin.getline(sendBuf, sizeof(sendBuf));
		send(sendsock, sendBuf, sizeof(sendBuf), 0);//    
		if (strcmp(sendBuf, "bye") == 0)
		{
			SetEvent(bExit);//    
			break;
		}
	}
	closesocket(sendsock);
	WSACleanup();//    
	return 0;
}

int main()
{
	//         
	WSADATA data;
	//WSAStartup(MAKEWORD(2, 0), &data);
	if (WSAStartup(MAKEWORD(2, 0), &data) != 0)// 0      
	{
		std::cout << "          !" << std::endl;
		return -1;
	}

	SOCKET client = socket(AF_INET, SOCK_STREAM, 0);//     
	if (client == INVALID_SOCKET)
	{
		std::cout << "       !" << std::endl;
		WSACleanup();//       
		return -1;
	}

	//        ,ip  ,  ,    
	sockaddr_in addr;
	addr.sin_addr.S_un.S_addr = inet_addr("192.168.0.103");
	addr.sin_family = AF_INET;
	addr.sin_port = htons(8888);

	std::cout << "   ......" << std::endl;
	int ret = connect(client, (SOCKADDR*)&addr, sizeof(addr));
	if (ret == -1)//  0      ,-1    
	{
		std::cout << "    !" << std::endl;
		return -1;
	}
	std::cout << "    !" << std::endl;

	//    ,       
	HANDLE send_thread, recv_thread;//         ,      
	DWORD nSthread, nRthread;    //       ID 
								 /*  CreateThread()    
								                
								               ,0    1MB
								                 
								                  ,             
								             ,         ,0             ,CREAT——SUSPENDED         ,    ResumeThread()  
								              
								 */
	send_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)sendMessage, (LPVOID)client, 0, &nSthread);//    
	recv_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)recvMessage, (LPVOID)client, 0, &nRthread);//    
																											/*               ,  bExit     ( SetEvent()         )
																											        
																											*/
	WaitForSingleObject(bExit, INFINITE);
	closesocket(client);
	WSACleanup();
	return 0;
}