C++ Socket打造简单聊天室|黑客技术流

2019-12-01  本文已影响0人  一只大蜘蛛

今天我们就来用C++来编写一个简单的聊天小程序,同时是想让大家了解一下C/S架构,看看服务器和客户端是怎样的一个通信流程。对于那些想编写远程控制的小伙伴,这些通信流程你必须要清楚。想实现服务器和客户端的通信,我们就必须要用到Socket(套接字)接口。Socket网络通信涉及到的俩种协议 一种是 TCP协议、还有一种就是UDP协议。俩种协议各有各的优点,不同的环境可以采用不用的协议。
本文章转载至《黑客技术流

image

接下来我们用到的通信协议是TCP协议,相比较用TCP协议进行通信 会比用UDP协议更加麻烦一些。TCP协议通信不仅需要编写一个服务端,而且还需要编写一个客户端

image

看着上面的图步骤还挺多的,用到的都是系统自带的Api函数。如果你没有Api编程开发基础,看到这里你已经很厉害了。建议你先去百度学习一下上面的几个Api函数在来看这篇文章,不然在接着看下去看不懂,自信心会很受打击的。服务端代码

<pre class="wp-block-preformatted">#include "stdafx.h"

include <Windows.h>

pragma comment(lib,"Ws2_32.lib")

SOCKET Srever, Client; //创建服务端 客户端套接字
bool Socket_Init(char *IP, int Port);//初始化
UINT Receive_Data(LPVOID lpVoid);//接收数据
void SendMsg(char *pszSend);//发送数据

int _tmain(int argc, _TCHAR* argv[])
{
if (0 == Socket_Init("127.0.0.1",7075))
{
printf("初始化监听端口失败!\n");
return 0;
}
printf("监听端口成功等待客户端连接!\n");

char SendData[MAX_PATH] = { 0 };
while (TRUE)
{
    gets(SendData);
    SendMsg(SendData);
}

return 0;

}

bool Socket_Init(char *IP, int Port)
{
//初始化Winsock库
WSADATA Data = { 0 };
::WSAStartup(MAKEWORD(2, 2), &Data);//2.2版本

//第一步创建socket
Srever = socket(AF_INET, SOCK_STREAM, 0);
if (Srever == INVALID_SOCKET) return 0;//创建失败就返回

//第二部 绑定端口

sockaddr_in addr;//创建结构体
addr.sin_family = AF_INET;//通信协议
addr.sin_addr.S_un.S_addr = ::inet_addr(IP);//IP
addr.sin_port = ::htons(Port);//端口
if (::bind(Srever, (sockaddr*)&addr, sizeof(addr)) != 0)return 0;//失败返回

//第三部 监听端口

if (listen(Srever, 5) != 0)return 0;//失败返回

//创建线程
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)Receive_Data,NULL, NULL, NULL);

}

UINT Receive_Data(LPVOID lpVoid)
{
//第四部 接受客户连接请求

sockaddr_in addr = { 0 };//创建结构体 用于获取客户IP
int  len = sizeof(addr);
Client = accept(Srever, (sockaddr*)&addr, &len);//接受客户端的连接

//第五步 接受数据
char StrBuf[MAX_PATH] = { 0 };//数据缓冲区
while (true)
{
    //
    if (recv(Client,StrBuf,MAX_PATH,0)<= 0) continue;
    printf("[她]%s\n", StrBuf);
}
return 0;

}

//第六步 发送数据
void SendMsg(char *pszSend)
{
// 发送数据
::send(Client, pszSend, (1 + ::lstrlen(pszSend)), 0);
printf("[我]%s\n", pszSend);
}</pre>

客户端代码

<pre class="wp-block-preformatted">#include "stdafx.h"

include <Winsock2.h>

pragma comment(lib, "Ws2_32.lib")

SOCKET Client;// 客户端套接字

//连接服务端
BOOL Connection(char *lpszServerIp, int iServerPort);
void SendMsg(char *pszSend);// 发送数据
UINT Receive_Data(LPVOID lpVoid);//多线程接收数据

int _tmain(int argc, _TCHAR* argv[])
{
// 连接到服务器
if (FALSE == Connection("127.0.0.1", 7075))
{
printf("Connection Error.\n");

}
printf("Connection OK.\n");

// 发送信息
char szSendBuf[MAX_PATH] = { 0 };
while (TRUE)
{
    gets(szSendBuf);
    // 发送数据
    SendMsg(szSendBuf);
}

return 0;

}

BOOL Connection(char *lpszServerIp, int iServerPort)
{
// 初始化 Winsock 库
WSADATA wsaData = { 0 };
::WSAStartup(MAKEWORD(2, 2), &wsaData);
// 创建流式套接字
Client = ::socket(AF_INET, SOCK_STREAM, 0);
if (INVALID_SOCKET == Client)
{
return FALSE;
}
// 设置服务端地址和端口信息
sockaddr_in addr = { 0 };
addr.sin_family = AF_INET;
addr.sin_port = ::htons(iServerPort);
addr.sin_addr.S_un.S_addr = ::inet_addr(lpszServerIp);
// 连接到服务器
if (0 != ::connect(Client, (sockaddr *)(&addr), sizeof(addr)))
{
return FALSE;
}
// 创建接收数据多线程
::CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)Receive_Data, NULL, NULL, NULL);

return TRUE;

}

// 发送数据
void SendMsg(char *pszSend)
{
// 发送数据
::send(Client, pszSend, (1 + ::lstrlen(pszSend)), 0);
printf("[我]%s\n", pszSend);
}

// 接收数据多线程
UINT Receive_Data(LPVOID lpVoid)
{
char szBuf[MAX_PATH] = { 0 };
while (TRUE)
{
// 接收数据
int iRet = ::recv(Client, szBuf, MAX_PATH, 0);
if (0 >= iRet)
{
continue;
}
printf("[她]%s\n", szBuf);
}
return 0;
}</pre>

通过上面一系列的代码,就可以实现服务端与客户端的通信了,因为为了写文章方便,我把所有的代码都集成到了一个CPP文件中。这样会显得不是很简洁,你们可以自行随意改动这些代码。

image

从上图可以看到,这样就完成了一次简单的通信了。因为用的是win32控制台程序编写的,所有看上去可能不是很理想。如果说是用MFC界面编写的话,估计我这篇文章写一下午都写不好。

上一篇 下一篇

猜你喜欢

热点阅读