WinSocket實現進程通信的一個簡單實例

    Windows下通過Socket可以使進程之間產生通信。

    設計上簡單地分爲服務端和客戶端。


服務端:

  1. 建立Socket
  2. 聲明自身的端口號和地址並綁定到Socket
  3. 使用Listen打開監聽,然後不斷用Accept去查看是否有連接,如果有,捕獲Socket,並通過Recv獲取消息的內容
  4. 通信完成後調用CloseSocket關閉這個對應Accept到的Socket,如果不再需要等待任何客戶端連接,那麼用CloseSocket關閉掉自身的Socket 
客戶端:
  1. 建立Socket
  2. 通過端口號和地址確定目標服務器,使用Connect連接到服務器
  3. send發送消息,等待處理
  4. 通信完成後調用CloseSocket關閉Socket

服務端代碼:
#pragma once

/*
ServerNet.h
服務端:建立Socket,聲明自身的端口號和地址並綁定到Socket,使用Listen打開監聽,
然後不斷用Accept去查看是否有連接,如果有,捕獲Socket,並通過Recv獲取消息的內容,
通信完成後調用CloseSocket關閉這個對應Accept到的Socket,如果不再需要等待任何客戶端連接,那麼用CloseSocket關閉掉自身的Socket
*/


#include<stdio.h>
#include<windows.h>

#pragma comment(lib, "Ws2_32.lib")

class ServerNet
{
private:
	SOCKET m_sock;
public:
	//  初始化服務器
	int ServerInit(const char* address, int port);

	// 更新數據
	void ServerRun();
};

/*
ServerNet.cpp
*/

#include"ServerNet.h"

/*服務器初始化*/
int ServerNet::ServerInit(const char* address, int port)
{
	int rlt = 0;

	int iErrorMsg;

	//初始化WinSock
	WSAData wsaData;
	iErrorMsg = WSAStartup(MAKEWORD(1, 1), &wsaData);

	if (iErrorMsg != NO_ERROR)
	{
		//初始化WinSock失敗
		printf("server wsastartup failed with error : %d\n", iErrorMsg);

		rlt = 1;
		return rlt;
	}

	// 創建服務器端socket

	m_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (m_sock == INVALID_SOCKET)
		// 創建socket出現了異常
	{
		printf("server socket failed with error: %d\n", WSAGetLastError());
		rlt = 2;
		return rlt;
	}

	// 聲明信息
	SOCKADDR_IN	servaddr;
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = port;
	servaddr.sin_addr.s_addr = inet_addr(address);

	//綁定
	iErrorMsg = bind(m_sock, (SOCKADDR*)&servaddr, sizeof(servaddr));
	if (iErrorMsg < 0)
	{
		//綁定失敗
		printf("bind failed with error : %d\n", iErrorMsg);
		rlt = 3;
		return rlt;
	}

	return rlt;
}

void ServerNet::ServerRun()
{
	// 公開連接
	listen(m_sock, 5);

	SOCKADDR_IN tcpAddr;
	int len = sizeof(sockaddr);
	SOCKET newSocket;
	char buf[1024];
	int rval;

	do
	{
		// 接收信息
		newSocket = accept(m_sock, (sockaddr*)&tcpAddr, &len);

		if (newSocket == INVALID_SOCKET)
		{
			// 非可用socket
			printf("invalid socket occured.\n");
		}
		else
		{
			// 可用的新socket連接
			printf("new socket connect: %d\n", newSocket);

			// 消息處理
			do
			{
				//printf("process\n");
				// 接收數據
				memset(buf, 0, sizeof(buf));
				rval = recv(newSocket, buf, 1024, 0);

				if (rval == SOCKET_ERROR)
					// 該異常通常發生在未closeSocket就退出時
				{
					printf("recv socket error.\n");
					break;
				}
					
				else if (rval == 0)
					// 0表示正常退出
					printf("socket %d connect end.\n", newSocket);
				else
					// 顯示接收到的數據
					printf("recv msg: %s\n", buf);
			} while (rval != 0);

			// 關於接收的socket
			closesocket(newSocket);
		}
	} while (1);

	// 關閉自身socket
	closesocket(m_sock);
}


#include"ServerNet.h"

int main()
{
	ServerNet serverNet;
	int iRlt = serverNet.ServerInit("127.0.0.1", 8888);
	if (iRlt == 0)
	{
		printf("servr init successful.\n");
		serverNet.ServerRun();
	}
	else
		printf("server init failed with error: %d\n", iRlt);
	system("pause");
}


客戶端代碼:
#pragma once

/*
ClinetNet.h
客戶網絡
*/

#include<stdio.h>
#include<windows.h>

#pragma comment(lib, "Ws2_32.lib")

class ClientNet
{
private:
	SOCKET m_sock;

public:
	// 連接指定的服務器
	int ClientConnect(int port, const char* address);
	// 發送信息
	int ClientSend(const char* msg, int len);
	// 關閉連接
	void ClientClose();
};


/*
ClientNet.cpp
*/

#include"ClientNet.h"

/*客戶端Socket連接*/
int ClientNet::ClientConnect(int port, const char* address)
{
	int rlt = 0;   //connectflag  0-success 1-WSAStartfailed 2-socketfailed 3-connectfailed

	// 記錄錯誤信息
	int iErrMsg;
	// 啓動WinSock
	WORD wVersionRequested;
	WSADATA wsaData;
	wVersionRequested = MAKEWORD(1, 1);
	iErrMsg = WSAStartup(wVersionRequested, &wsaData);
	if (iErrMsg != NO_ERROR)
		// WSAStartup出現了錯誤
	{
		printf("failed with WSAStartup error: %d\n", iErrMsg);
		rlt = 1;
		return rlt;
	}

	// 創建Socket
	m_sock = socket(AF_INET, SOCK_STREAM, 0);
	if (m_sock==INVALID_SOCKET)
		// socket出現了錯誤
	{
		printf("failed with socket error: %d\n", WSAGetLastError());
		rlt = 2;
		return rlt;
	}


	// 目標服務器數據
	SOCKADDR_IN servaddr;
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = port;
	servaddr.sin_addr.s_addr = inet_addr(address);

	// sock與目標服務器連接
	iErrMsg = connect(m_sock, (SOCKADDR*)&servaddr, sizeof(servaddr));
	if (iErrMsg != NO_ERROR)
	{
		printf("failed with connect error: %d\n", iErrMsg);
		rlt = 3;
		return rlt;
	}

	// success
	return rlt;

}

/*客戶端發送消息*/
int ClientNet::ClientSend(const char* msg, int len)
{
	int rlt = 0;

	int iErrMsg = 0;

	// 指定sock發送消息
	iErrMsg = send(m_sock, msg, len, 0);
	if (iErrMsg < 0)
		// 發送失敗
	{
		printf("send msg failed with error: %d\n", iErrMsg);
		rlt = 1;
		return rlt;
	}
	printf("send msg successfully\n");
	return rlt;
}

/*客戶端關閉Socket*/
void ClientNet::ClientClose()
{
	closesocket(m_sock);
}

#include<iostream>
#include<string>
#include"ClientNet.h"

using namespace std;

int main()
{
	ClientNet client;
	int rlt = 0;
	string msg;
	//memset(msg, 0, sizeof(msg));

	//連接到127.0.0.1(即本地),端口號爲8888的服務端
	printf("connecting.....\n");
	rlt = client.ClientConnect(8888, "127.0.0.1");

	if (rlt == 0)
		// socket連接成功
	{
		//發送消息
		printf("	connect successfully. input  q to quit\n");
		printf("-------------------------\n");
		while (1)
		{
			printf("msg input: ");
			getline(cin, msg);
			if (msg == "q")
				break;
			else
			{
				printf("sending msg.....\n");
				rlt = client.ClientSend(msg.c_str(), msg.length());
			}
			
		}
		

		// 關閉socket
		printf("closing socket.....\n");
		client.ClientClose();


	}

	system("pause");

	return 0;

}


通信示例如下圖:





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章