【C/C++ SOCKET编程】基于TCP协议实现服务器客户端的简单通信

什么是SOCKET

Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。

TCP/IP协议

从字面意义上讲,有人可能会认为 TCP/IP 是指 TCP 和 IP 两种协议。实际生活当中有时也确实就是指这两种协议。然而在很多情况下,它只是利用 IP 进行通信时所必须用到的协议群的统称。具体来说,IP 或 ICMP、TCP 或 UDP、TELNET 或 FTP、以及 HTTP 等都属于 TCP/IP 协议。他们与 TCP 或 IP 的关系紧密,是互联网必不可少的组成部分。TCP/IP 一词泛指这些协议,因此,有时也称 TCP/IP 为网际协议群。

互联网进行通信时,需要相应的网络协议,TCP/IP 原本就是为使用互联网而开发制定的协议族。因此,互联网的协议就是 TCP/IP,TCP/IP 就是互联网的协议。

具体详解点这个

Socket编程

基本流程

【C/C++ SOCKET编程】基于TCP协议实现服务器客户端的简单通信_第1张图片

 头文件

#include
#include
#include
#pragma comment(lib,"ws2_32.lib")

server创建绑定、监听、连接

//定义服务端套接字,接受请求套接字
	SOCKET s_server;
	SOCKET s_accept;
	//服务端地址客户端地址
	SOCKADDR_IN server_addr;
	SOCKADDR_IN accept_addr;
	//打开
	WORD w_req = MAKEWORD(2, 2);//版本号
	WSADATA wsadata;//结构体:拿到版本,版本校验 
	int err;
	err = WSAStartup(w_req, &wsadata);//查看是否打开成功
	if (err != 0)
	{
		cout << "打开失败!" << endl;
	}
	else {
		cout << "打开成功!" << endl;
	}
	//检测版本号
	if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wHighVersion) != 2)
	{
		cout << "版本号不符!" << endl;
		WSACleanup();
	}
	else {
		cout << "版本正确!" << endl;
	}
	//填充服务端地址信息

	//填充服务端信息
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	server_addr.sin_port = htons(7777);
	//创建套接字
	s_server = socket(AF_INET, SOCK_STREAM, 0);
	if (bind(s_server, (SOCKADDR*)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR)
	{
		cout << "bind失败!" << endl;
		WSACleanup();
	}
	else {
		cout << "bind成功!" << endl;
	}
	//监听
	if (listen(s_server, SOMAXCONN) < 0)
	{
		cout << "设置监听状态失败!" << endl;
		WSACleanup();
	}
	else {
		cout << "设置监听状态成功!" << endl;
	}
	cout << "服务端正在监听连接,请稍候...." << endl;

//接受连接请求
	len = sizeof(SOCKADDR);
	s_accept = accept(s_server, (SOCKADDR*)&accept_addr, &len);
	if (s_accept == SOCKET_ERROR)
	{
		cout << "连接失败!" << endl;
		WSACleanup();
		return 0;
	}
	cout << "连接成功" << endl;

client创建、连接

    SOCKET s_server;
	SOCKET c_client;
	//服务端地址客户端地址
	SOCKADDR_IN server_addr;
	SOCKADDR_IN client_addr;
	//定义主机名
	char localhostname[256];
	//打开
	WORD w_req = MAKEWORD(2, 2);//版本号
	WSADATA wsadata;
	int err;
	err = WSAStartup(w_req, &wsadata);//查看是否打开成功 
	if (err != 0)
	{
		cout << "打开失败!" << endl;
	}
	else {
		cout << "打开成功!" << endl;
	}
	//检测版本号
	if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wHighVersion) != 2)
	{
		cout << "版本号不符!" << endl;
		WSACleanup();
	}
	else {
		cout << "版本正确!" << endl;
	}
	//绑定地址
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	server_addr.sin_port = htons(7777);//转换为小端存储
	//创建套接字
	s_server = socket(AF_INET, SOCK_STREAM, 0);
	c_client = socket(AF_INET, SOCK_STREAM, 0);
	if (connect(s_server, (SOCKADDR*)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR)
	{
		cout << "服务器连接失败!" << endl;
		WSACleanup();
	}
	else {
		cout << "服务器连接成功!" << endl;
	}

发送send()

功能:向套接字中发送数据

参数:sockfd:向套接字中发送数据

           buf:要发送的数据的首地址

           len:要发送的数据的字节

           int flags:设置为MSG_DONTWAITMSG 时 表示非阻塞

                           设置为0时功能和write一样

返回值:成功返回实际发送的字节数

            失败:返回 -1

char send_buf[100];
int send_len = send(s_accept, send_buf, sizeof(send_buf), 0);
if (send_len < 0)
{
	cout << "发送失败!" << endl;
}

接收recv()

功能:向套接字中发送数据

参数:sockfd:从哪个套接字接

           buf:存放要接收的数据的首地址

           len:要接收的数据的字节

           int flags:设置为MSG_DONTWAITMSG 时 表示非阻塞

                           设置为0时 功能和read一样

返回值:成功返回实际发送的字节数

            失败:返回 -1

char recv_buf[100];
int recv_len = recv(s_accept, recv_buf, sizeof(recv_buf), 0);
if (recv_len < 0)
{
	cout << "接受失败!" << endl;
}
else cout << "客户端信息:" << recv_buf << endl;

关闭套接字、释放资源

//关闭套接字
	closesocket(s_server);
	closesocket(s_accept);
	//释放DLL资源
	WSACleanup();

你可能感兴趣的:(网络编程,c++,tcp/ip)