1. 服务端

#include <iostream>
#include <signal.h>
#include <forward_list>
#include <thread>
#include <WinSock2.h>
#include <Windows.h>
#pragma comment(lib, "Ws2_32.lib") class Server {
constexpr static int DEFAULT_BACKLOG = 10;
public:
Server(): _listener(INVALID_SOCKET), _should_exit(false) {}
~Server() {
for (auto it = _threads.begin(); it != _threads.end(); it++) {
it->join();
}
} // 判断 server 是否有效
operator bool() const {
return _listener != INVALID_SOCKET;
} // 监听并接受客户端连接
void listen_and_serve(unsigned short port, int backlog= DEFAULT_BACKLOG) {
// 初始化 WSA
WORD socketVersion = MAKEWORD(2, 2);
WSADATA wsaData;
if (WSAStartup(socketVersion, &wsaData) != 0) {
std::cerr << "cannot start up\n";
return;
} // 创建套接字
_listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (_listener == INVALID_SOCKET) {
std::cerr << "cannot create listener\n";
return;
} // 设置套接字选项
int value = 1;
if (setsockopt(_listener, SOL_SOCKET, SO_REUSEADDR, (char*)&value, sizeof(value)) == SOCKET_ERROR) {
std::cerr << "cannot set option: reuse_address\n";
} // 绑定地址
memset(&addr, 0, sizeof(sockaddr_in));
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
if (bind(_listener, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR) {
std::cerr << "bind failed\n";
return;
} // 监听连接
if (listen(_listener, backlog) == SOCKET_ERROR) {
std::cerr << "listen failed\n";
return;
} SOCKET conn;
std::cout << "listening ...\n"; // 接受连接
while (!_should_exit) {
conn = accept(_listener, NULL, NULL);
if (conn == INVALID_SOCKET) {
std::cerr << "accept failed\n";
} // 启动线程去处理客户端连接
_threads.push_front(std::thread(SetServer::handle_connection, conn));
}
} // 关闭、完成善后工作
void close() {
_should_exit = true;
closesocket(_listener);
WSACleanup();
} // 处理客户端连接
static void handle_connection(SOCKET conn) {
char buf[16] = { 0 };
int n = recv(conn, buf, sizeof(buf), 0);
send(conn, buf, n, 0);
closesocket(conn);
} private:
SOCKET _listener;
std::forward_list<std::thread> _threads;
bool _should_exit;
}; Server server; // 信号处理器
void handler(int signum) {
std::cout << "exit ...\n";
if (server) {
server.close();
}
exit(EXIT_SUCCESS);
} int main() {
// 处理 ctrl+c
signal(SIGINT, handler); server.listen_and_serve(6666);
}

2. 客户端

#pragma once

#include <iostream>
#include <WS2tcpip.h>
#include <WinSock2.h>
#include <Windows.h>
#pragma comment(lib, "Ws2_32.lib") const char* SERVER_IP = "127.0.0.1";
const short SERVER_PORT = 6666; int main() {
// 初始化 WSA
WORD socketVersion = MAKEWORD(2, 2);
WSADATA wsaData;
if (WSAStartup(socketVersion, &wsaData) != 0) {
std::cerr << "cannot start up\n";
return 1;
} // 创建套接字
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
std::cerr << "cannot create socket\n";
return 1;
} // 发起连接
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(SERVER_PORT);
inet_pton(AF_INET, SERVER_IP, &addr.sin_addr);
if (connect(sock, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR) {
std::cerr << "connect failed\n";
return 1;
} // 发送、接收数据
const char* msg = "hello";
char buf[16] = { 0 };
send(sock, msg, strlen(msg), 0);
int n = recv(sock, buf, sizeof(buf), 0);
std::cout << buf << std::endl; closesocket(sock);
return 0;
}

参考资料

https://blog.csdn.net/weixinhum/article/details/81742248

网络编程 — Windows TCP服务端和客户端的更多相关文章

  1. 网络编程 — Linux TCP服务端和客户端

    1. 服务端 #include <stdlib.h> #include <string.h> #include <errno.h> #include <sig ...

  2. 基于Select模型的Windows TCP服务端和客户端程序示例

    最近跟着刘远东老师的<C++百万并发网络通信引擎架构与实现(服务端.客户端.跨平台)>,Bilibili视频地址为C++百万并发网络通信引擎架构与实现(服务端.客户端.跨平台),重新复习下 ...

  3. python网络编程:socket、服务端、客户端

    本文内容: socket介绍 TCP: 服务端 客户端 UDP: 服务端 客户端 首发时间:2018-02-08 01:14 修改: 2018-03-20 :重置了布局,增加了UDP 什么是socke ...

  4. python网络编程-TCP服务端的开发

    #TCP服务端开发 2 #方法说明 3 """ 4 bind(host,port)表示绑定端口号,host是ip地址,ip地址一般不进 行绑定,表示本机的任何一个ip地址 ...

  5. [javaSE] 网络编程(TCP服务端客户端互访阻塞)

    客户端给服务端发送数据,服务端收到数据后,给客户端反馈数据 客户端: 获取Socket对象,new出来,构造参数:String的ip地址,int的端口号 调用Socket对象的getOutputStr ...

  6. TCP/IP网络编程之多线程服务端的实现(二)

    线程存在的问题和临界区 上一章TCP/IP网络编程之多线程服务端的实现(一)的thread4.c中,我们发现多线程对同一变量进行加减,最后的结果居然不是我们预料之内的.其实,如果多执行几次程序,会发现 ...

  7. TCP/IP网络编程之多进程服务端(二)

    信号处理 本章接上一章TCP/IP网络编程之多进程服务端(一),在上一章中,我们介绍了进程的创建和销毁,以及如何销毁僵尸进程.前面我们讲过,waitpid是非阻塞等待子进程销毁的函数,但有一个不好的缺 ...

  8. 【转】TCP/UDP简易通信框架源码,支持轻松管理多个TCP服务端(客户端)、UDP客户端

    [转]TCP/UDP简易通信框架源码,支持轻松管理多个TCP服务端(客户端).UDP客户端 目录 说明 TCP/UDP通信主要结构 管理多个Socket的解决方案 框架中TCP部分的使用 框架中UDP ...

  9. swoole创建TCP服务端和客户端

    服务端: server.php <?php //创建Server对象,监听 127.0.0.1:9501端口    $serv = new swoole_server("127.0.0 ...

随机推荐

  1. Python-其他-round()保留小数位时遇到的问题

    最近有一个需求,原有整数计算,改成小数计算,保留一位小数. 于是按照需求,将数据结构由 int 改为 float ,计算时采用round()方法来保留小数位. 第一版代码如下: a = 0.10000 ...

  2. C#中使用NPOI提示(找到的程序集清单定义与程序集引用不匹配)

    问题 找到的程序集清单定义与程序集引用不匹配. (异常来自 HRESULT:0x80131040) 描述 使用NPOI导出word文档,需要C#的解压缩类,所以引用了ICSharpCode.Sharp ...

  3. Excel 快速跳到表格最后一行/第一行

    快速跳到表格的最后一行 首先鼠标选中一个带有数据的单元格,点击shift键,把鼠标放到该单元格底部的边缘地带,出现带四个方向的箭头为止,再连续点击鼠标左键两次,直接跳到表格的最后一行 快速跳到表格的最 ...

  4. JDBC数据库删除

    1 //删除操作: 2 3 if(conn != null){ 4 String temps="2"; 5 conn.setAutoCommit(false); 6 Prepare ...

  5. .NET Core学习笔记(8)——Entity Framework Core之Database First

    曾经我以为再也不会去弄啥Database First,然鹅我错了.这个世界上就是有啪啪打脸和真香的时候.当小伙伴拿着做好的DB表结构和SQL脚本递过来的时候,我知道我没法拒绝.望着他突起的肱二头肌和充 ...

  6. 入门oj 6492: 小B的询问

    Description 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L ...

  7. 使用纯 CSS 实现滚动阴影效果

    开门见山,有这样一种非常常见的情况,对于一些可滚动的元素而言.通常在滚动的时候会给垂直于滚动的一侧添加一个阴影,用于表明当前有元素被滚动给该滚出了可视区域,类似这样: 可以看到,在滚动的过程中,会出现 ...

  8. java:原子类的CAS

    当一个处理器想要更新某个变量的值时,向总线发出LOCK#信号,此时其他处理器的对该变量的操作请求将被阻塞,发出锁定信号的处理器将独占共享内存,于是更新就是原子性的了. 1.compareAndSet- ...

  9. Vue自动化路由(基于Vue-Router)开篇

    vue自动化路由 好久不见~ 若羽又开篇Vue的内容了. 年初的时候发布了第一版的ea-router自动化路由库,欢迎大家安装使用.[Github地址] [npm地址] 经历一年的使用.还是发现了不少 ...

  10. MySQL审计audit

    导读: MySQL社区版是不带审计功能的,如果要使用MySQL审计,可以考虑使用中间件(例如proxysql)或者是MariaDB的审计插件.这里以MariaDB的审计插件为例,实现MySQL 5.7 ...