Windows下通過Socket可以使進程之間產生通信。
設計上簡單地分爲服務端和客戶端。
服務端:
- 建立Socket
- 聲明自身的端口號和地址並綁定到Socket
- 使用Listen打開監聽,然後不斷用Accept去查看是否有連接,如果有,捕獲Socket,並通過Recv獲取消息的內容
- 通信完成後調用CloseSocket關閉這個對應Accept到的Socket,如果不再需要等待任何客戶端連接,那麼用CloseSocket關閉掉自身的Socket
- 建立Socket
- 通過端口號和地址確定目標服務器,使用Connect連接到服務器
- send發送消息,等待處理
- 通信完成後調用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;
}