C++ socket 网络编程
一:介绍
1、什么是TCP/IP?
TCP提供基于IP环境下的数据可靠性传输,
事先需要进行三次握手来确保数据传输的可靠性。
详细的不再赘述,感兴趣的朋友可以去search一下。
2、什么是socket?
socket顾名思义就是套接字的意思,
用于描述地址和端口,是一个通
信链的句柄。应用程序通过socket
向网络发出请求或者回应。
socket编程有三种:(1)流式套接字(SOCK_STREAM)
(2)数据报套接字(SOCK_DGRAM),
(3)原始套接字(SOCK_RAW),前两者较常用。
基于TCP的socket编程是流式套接字。
二:client/server即C/S模式:
TCP/IP通信中,主要是进行C/S交互。下面看看具体交互内容:
1: 服务端:
(1)建立socket -----> socket()
(2)绑定端口 ------> bind()
(3)监听 --------> listen()
(4)等待client链接 ------> accept()
(5)接受数据 --------> recv()
(6)发送数据 --------> send()
(7)关闭socket---------> closesocket()
2:客户端:
(1)建立socket -----> socket()
(2)链接服务器 -----> connect()
(3)发送数据 --------> send()
(4)接受数据 --------> recv()
(5)关闭socket --------> closesocket()
注意:windows下应先加载链接库并创建socket网络环境
1: 加载链接库:
#pragma comment(lib,“ws2_32.lib”);
2: 创建网洛环境
WORD word = MAKEWORD(2,2); // 创建版本号
WSDATA data;
WSAStartup(word, &data);// 启动网络环境
在程序最后要清除网络环境:WSACleanup();
int main()
{
WORD word = MAKEWORD(2,2);// 创建版本号
WSADATA data;
WSAStartup(word,&data);// 启动网络环境
/*
这里写逻辑
*/
WSACleanup();//清除网络环境
return 0;
}
三:server端代码:
#include<windows.h>
#include <WinSock2.h>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")//加载链接库
using namespace std;//使用命名空间std
int main()
{
//windows环境下先创建socket环境
WORD word = MAKEWORD(2,2);//创建版本号
WSADATA data;
WSAStartup(word,&data);//启动网络环境
//--------------------------------------
// 1 建立一个Socket
//IPPROTO_TCP可以用0代替,客户端使用0
SOCKET _sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// 2 bind 绑定用于接收客户端连接的网络端口
//创建一个地址结构实列_sin
sockaddr_in _sin = {};
//IPv4
_sin.sin_family = AF_INET;
//端口号
_sin.sin_port = htons(4567);//htons --> host to net unsigned short
//绑定到哪个地址。 (INADDR_ANT本机的所有网络地址)
_sin.sin_addr.S_un.S_addr = INADDR_ANY;//也可单个inet_addr("127.0.0.1")
if (SOCKET_ERROR == bind(_sock, (sockaddr*)&_sin, sizeof(_sin)))
{
cout << "绑定网络端口失败.........." << endl;
}
else
{
cout << "绑定网络端口成功..............." << endl;
}
// 3 listen 监听网络端口
if (SOCKET_ERROR == listen(_sock, 5))
{
cout << "监听网络端口失败........" << endl;
}
else
{
cout << "监听网络端口成功......." << endl;
}
// 4 accept 等待接收客户端连接
sockaddr_in clientAddr = {};
int nAddrLen = sizeof(clientAddr);
SOCKET _csoke = INVALID_SOCKET;//设置无效的Socket
//无效Socket 用于保存新加入的客户端
while (true)
{
_csoke = accept(_sock, (sockaddr*)&clientAddr, &nAddrLen);
//INVALID_SOCKET 可以用0 替换
if (INVALID_SOCKET == _csoke)
{
cout << "接受到无效的客户端SOCKET......." << endl;
}
//inet_ntoa()将网络地址转换成“.”点隔的字符串格式
cout << "新客户端加入: IP = " << inet_ntoa(clientAddr.sin_addr) << endl;
// 5 send 向客户端发送一条数据
char msgBUF[] = "hello ,I'm server.";
//send(客户端socket,要发送的数据,要发送多长,0);
//strlen()计算数据的大小,+1后给结束符留个地方
send(_csoke, msgBUF, strlen(msgBUF) + 1, 0);
}
// 6 关闭套接字Closesocket
closesocket(_sock);
//--------------------------------------
//清除网络环境
WSACleanup();
}
四:客户端代码
#include <Windows.h>
#include <WinSock2.h>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")//加载链接库
using namespace std;
int main()
{
//创建网络环境
WORD word = MAKEWORD(2, 2);
WSADATA data;
WSAStartup(word, &data);
//------------------
// 1 建立Socket
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if (SOCKET_ERROR == sock)
{
cout << "ERROR ,建立socket失败......." << endl;
}
else
{
cout << "SUCEED, 建立socket成功......" << endl;
}
// 2 链接服务器 connect
sockaddr_in sin = {};
sin.sin_family = AF_INET;
sin.sin_port = htons(4567);
sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
int ret = connect(sock, (sockaddr*)&sin, sizeof(sin));
if (SOCKET_ERROR == ret)
{
cout << "建立socket链接失败......" << endl;
}
else
{
cout << "建立socket链接成功....." << endl;
}
// 3 接受服务器信息
//recBufi消息缓冲区
char recBuf[256] = {};
int recLen = recv(sock, recBuf, 256, 0);
if (recLen > 0)
{
cout << "接受的数据: " << recBuf << endl;
}
// 4 关闭套接字closesocket
closesocket(sock);
//------------------
//清楚网络环境
WSACleanup();
getchar();
return 0;
}