相关文章推荐:
Socket 编程基础
面试官,不要再问我三次握手和四次挥手
TCP的三次握手与四次挥手
参考视频:
https://www.bilibili.com/video/BV1aW4y1w7Ui/?spm_id_from=333.337.search-card.all.click
TCP通信流程
服务端
#include<iostream>
#include<cstring>
#include<WinSock2.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
int main(void)
{
//Windows上使用网络功能需要开启网络权限
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
//1.创建socket套接字
//SOCKET socket{
// int af, //协议地址簇 IPV4/IPV6 AF_INET/AF_INET6
// int type, //类型 流式协议/帧式协议 SOCK_STREAM/SOCK_DGRAM
// int protocol //保护协议 0
//};
SOCKET listen_socket = socket(AF_INET, SOCK_STREAM, 0);
if (listen_socket == INVALID_SOCKET) {
cerr << "error" << endl;
return -1;
}
//2.给这个socket绑定一个端口号
//struct sockaddr_in {
// ADDRESS_FAMILY sin_family; //协议地址簇
// USHORT sin_port; //端口号
// IN_ADDR sin_addr; //IP地址
// CHAR sin_zero[8]; //保留字节
//};
struct sockaddr_in local = { 0 };
local.sin_family = AF_INET;
local.sin_port = htons(9999); //大小端问题 中间设备使用的是大端序(路由器)
local.sin_addr.s_addr = INADDR_ANY; //表示接受任意网卡的数据
//bind(
// SOCKET s,
// const struct sockaddr* name,
// int namelen
//);
if (bind(listen_socket, (struct sockaddr*)&local, sizeof local) == INVALID_SOCKET) {
cerr << "error" << endl;
return -1;
}
//3.给这个socket开启监听属性
//listen(
// SOCKET s,
// int backlog
//);
if (listen(listen_socket, 128) == -1) {
cerr << "error" << endl;
return -1;
}
//4.等待客户端连接
// 返回的客户端socket才是跟客户端可以通讯的socket
// 阻塞函数,等到有客户端连接进来就接受连接,然后返回,否则就阻塞
//accept(
// SOCKET s,
// struct sockaddr* addr,
// int* addrlen
//);
while (true) {
SOCKET client_socket = accept(listen_socket, nullptr, nullptr);
if (client_socket == INVALID_SOCKET) {
continue;
}
//5.开始通讯(B/S)
//recv(
// SOCKET s, //客户端socket
// char* buf, //要接受的数据存储的位置
// int len, //接受的长度
// int flags //0
//);
//send(
// SOCKET s, //客户端socket
// const char* buf, //要发送的数据存储的位置
// int len, //长度
// int flags //0
//);
char buffer[1024] = { 0 };
int ret = recv(client_socket, buffer, sizeof buffer, 0);
cout << buffer << endl;
send(client_socket, buffer, strlen(buffer), 0);
//6.关闭连接
closesocket(client_socket);
}
return 0;
}
客户端
#include<iostream>
#include<cstring>
#include<Winsock2.h>
#include<WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
int main(void)
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
//1.创建socket套接字
SOCKET client_socket = socket(AF_INET, SOCK_STREAM, 0);
if (client_socket == INVALID_SOCKET) {
cerr << "error" << endl;
return -1;
}
//2.连接服务器
struct sockaddr_in target;
target.sin_family = AF_INET;
target.sin_port = htons(9999); //与服务端端口一致
inet_pton(AF_INET, "127.0.0.1", &target.sin_addr.s_addr); //转换本地环回地址
//target.sin_addr.s_addr = inet_addr("127.0.0.1");
//connect(
// SOCKET s,
// const struct sockaddr* name,
// int namelen
//);
if (connect(client_socket, (struct sockaddr*)&target, sizeof target) == INVALID_SOCKET) {
cerr << "error" << endl;
closesocket(client_socket);
return -1;
}
//3.开始通讯 send recv
while (true) {
char buffer1[1024] = { 0 };
cout << "enter: ";
cin >> buffer1;
send(client_socket, buffer1, strlen(buffer1), 0);
char buffer2[1024] = { 0 };
int ret = recv(client_socket, buffer2, sizeof buffer2, 0);
if (ret <= 0) {
break;
}
cout << buffer2 << endl;
}
//4.关闭连接
closesocket(client_socket);
return 0;
}
服务端完整代码
#include<iostream>
#include<cstring>
#include<WinSock2.h>
#include<thread>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
int main(void)
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET listen_socket = socket(AF_INET, SOCK_STREAM, 0);
if (listen_socket == INVALID_SOCKET) {
cerr << "error" << endl;
return -1;
}
struct sockaddr_in local = { 0 };
local.sin_family = AF_INET;
local.sin_addr.s_addr = INADDR_ANY;
local.sin_port = htons(9999);
if (bind(listen_socket, (struct sockaddr*)&local, sizeof local) == INVALID_SOCKET) {
cerr << "error" << endl;
return -1;
}
if (listen(listen_socket, 128) == -1) {
cerr << "error" << endl;
return -1;
}
while (true){
SOCKET client_socket = accept(listen_socket, nullptr, nullptr);
if (client_socket == INVALID_SOCKET) {
continue;
}
cout << "client connect: " << client_socket << endl;
thread th([](SOCKET client_socket){
while (true) {
char buffer[1024] = { 0 };
int ret = recv(client_socket, buffer, sizeof buffer, 0);
if (ret <= 0) {
cout << "client disconnect: " << client_socket << endl;
break;
}
cout << buffer << endl;
send(client_socket, buffer, strlen(buffer), 0);
}
closesocket(client_socket);
}, client_socket);
th.detach();
}
return 0;
}
客户端完整代码
#include<iostream>
#include<cstring>
#include<Winsock2.h>
#include<WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
int main(void)
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET client_socket = socket(AF_INET, SOCK_STREAM, 0);
if (client_socket == INVALID_SOCKET) {
cerr << "error" << endl;
return -1;
}
struct sockaddr_in target;
target.sin_family = AF_INET;
target.sin_port = htons(9999);
inet_pton(AF_INET, "127.0.0.1", &target.sin_addr.s_addr);
if (connect(client_socket, (struct sockaddr*)&target, sizeof target) == INVALID_SOCKET) {
cerr << "error" << endl;
closesocket(client_socket);
return -1;
}
while (true) {
char buffer1[1024] = { 0 };
cout << "enter: ";
cin >> buffer1;
send(client_socket, buffer1, strlen(buffer1), 0);
char buffer2[1024] = { 0 };
int ret = recv(client_socket, buffer2, sizeof buffer2, 0);
if (ret <= 0) {
cout << "server disconnect." << endl;
}
cout << buffer2 << endl;
}
closesocket(client_socket);
return 0;
}