windows socket编程入门示例3
// Lock.h
#ifndef _Lock_H
#define _Lock_H
#include <windows.h>class CriticalSection
{
private:CRITICAL_SECTION g_cs; //临界区 public:CriticalSection();~CriticalSection();void Lock();void UnLock();
};
#endif// Lock.cpp
#include "Lock.h"CriticalSection::CriticalSection()
{InitializeCriticalSection(&g_cs); //必须先初始化临界区
}CriticalSection::~CriticalSection()
{DeleteCriticalSection(&g_cs); //删除临界区
}void CriticalSection::Lock()
{EnterCriticalSection(&g_cs); //进入临界区(申请钥匙,得到钥匙)
}void CriticalSection::UnLock()
{LeaveCriticalSection(&g_cs); //离开(放弃钥匙,不再拥有)
}// tcpSocketSelect.cpp
#include <stdio.h>
#include <winsock2.h>
#include "Lock.h"#pragma comment(lib,"ws2_32.lib")#define IP_ADDRESS "127.0.0.1"
#define PORT 5678
#define MSGSIZE 8192 // window操作系统默认socket收发缓存大小是8Kstatic volatile bool isRunning;
static int volatile g_iTotalConn = 0;
static SOCKET g_CliSocketArr[FD_SETSIZE];// FD是File Describle文件描述符,也就是socket文件描述符(句柄)
CriticalSection criticalSectionLock;class SelectModel
{
public:static DWORD WINAPI WorkerThread(LPVOID lpParameter); // 服务器端工作线程int Process();
};int SelectModel::Process()
{int retCode;WORD wVersionRequested;WSADATA wsaData;SOCKET sListen, sClient;SOCKADDR_IN local, client;int iaddrSize = sizeof(SOCKADDR_IN);DWORD dwThreadId;// Initialize Windows socket librarywVersionRequested = MAKEWORD(2, 2);retCode = WSAStartup(wVersionRequested, &wsaData);if (retCode != 0){fprintf(stderr, "Load WSADTATA failed!\n");return -1;}if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){fprintf(stderr, "WSADTATA version error!\n");WSACleanup();return -1;}// Create listening socketsListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (sListen == INVALID_SOCKET){fprintf(stderr, "invalid socket !\n");WSACleanup();return -1;}local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);local.sin_family = AF_INET;local.sin_port = htons(PORT);int opt = 1;retCode = setsockopt(sListen, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt));if (retCode < 0){printf("setsockopt Failed.\n");closesocket(sListen);WSACleanup();return -1;}retCode = bind(sListen, (struct sockaddr *)&local, sizeof(SOCKADDR_IN));if (retCode == SOCKET_ERROR){printf("bind error !");closesocket(sListen);WSACleanup();return -1;}retCode = listen(sListen, 16);if (retCode == SOCKET_ERROR){printf("listen error !");closesocket(sListen);WSACleanup();return -1;}isRunning = true;// Create worker threadHANDLE serviceSubThread = CreateThread(NULL, 0, WorkerThread, NULL, 0, &dwThreadId);if (serviceSubThread == NULL){fprintf(stderr, "Create service sub thread failed!\n");goto END;}fprintf(stderr, "Server is running......\n");while (TRUE){sClient = accept(sListen, (struct sockaddr *)&client, &iaddrSize);if (sClient == INVALID_SOCKET){fprintf(stderr, "Invalid socket, continue to accept new socket!\n");continue;}criticalSectionLock.Lock();if (g_iTotalConn < FD_SETSIZE){g_CliSocketArr[g_iTotalConn++] = sClient;printf("Accepted client:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));}else{closesocket(sClient);printf("refuse client:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));}criticalSectionLock.UnLock();}END:closesocket(sListen);WSACleanup();return 0;
}DWORD SelectModel::WorkerThread(LPVOID lpParam)
{int i = 0;fd_set fdread;int ret = 0;struct timeval tv = { 1, 0 };// 1是阻塞等待1秒钟返回一次,后面的0是0毫秒char szMessage[MSGSIZE];while (isRunning){FD_ZERO(&fdread);//将fdread初始化空集int totalConn = g_iTotalConn;for (i = 0; i < totalConn; i++)// 可以在这里分段处理64个,用以支持多于64个的连接select.FD_SET(g_CliSocketArr[i], &fdread);//将要检查的套接口加入到集合中ret = select(MSGSIZE + 1, &fdread, NULL, NULL, &tv);//每隔一段时间,检查可读性的套接口,将可读的拷贝到fdread里面if (ret == 0)continue;for (i = 0; i < totalConn; i++){if (FD_ISSET(g_CliSocketArr[i], &fdread)) //如果可读{// A read event happened on g_CliSocketArrret = recv(g_CliSocketArr[i], szMessage, MSGSIZE, 0);if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET)){// Client socket closedprintf("Client socket %d closed.\n", g_CliSocketArr[i]);closesocket(g_CliSocketArr[i]);criticalSectionLock.Lock();for (int j = i; j < g_iTotalConn - 1; j++)g_CliSocketArr[j] = g_CliSocketArr[j + 1];g_iTotalConn--;i--;totalConn--;criticalSectionLock.UnLock();}else{printf("ret = %d \n", ret);if (ret == MSGSIZE || ret < 0){fprintf(stderr, "an error happened.\n");closesocket(g_CliSocketArr[i]);criticalSectionLock.Lock();for (int j = i; j < g_iTotalConn - 1; j++)g_CliSocketArr[j] = g_CliSocketArr[j + 1];g_iTotalConn--;i--;totalConn--;criticalSectionLock.UnLock();}else{szMessage[ret] = '\0';// 根据需要处理接收到的消息printf("Received a message from client:%s\n", szMessage);// 根据需要是否需要发送消息send(g_CliSocketArr[i], szMessage, strlen(szMessage), 0);}}}// 可读//else if (FD_ISSET(g_CliSocketArr[i], &fdread))}// for}// whilereturn 0;
}int main()
{SelectModel tcpServer;tcpServer.Process();return 0;
}// tcpSocketSelectClient.cpp
#include <WINSOCK2.H>
#include <stdio.h>#pragma comment(lib,"ws2_32.lib")#define IP_ADDRESS "127.0.0.1"
#define PORT 5678
#define MSGSIZE 8192 // window操作系统默认socket收发缓存大小是8KWSADATA wsaData;
SOCKET sClient;
SOCKADDR_IN server;
char szMessage[MSGSIZE];static void CheckBuffer(SOCKET &socket)
{//window 7,sock2,默认内核发送缓存和接收缓存都是8K.int sendbuflen = 0;int len = sizeof(sendbuflen);getsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char*)&sendbuflen, &len);printf("default,sendbuf:%d\n", sendbuflen);getsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char*)&sendbuflen, &len);printf("default,recvbuf:%d\n", sendbuflen);/*sendbuflen = 10240;setsockopt(clientSocket, SOL_SOCKET, SO_SNDBUF, (void*)&sendbuflen, len); */
}static bool LoadWSAData(WSADATA &wsaData)
{// Initialize Windows socket library WORD wVersionRequested = MAKEWORD(2, 2);// MAKEWORD的作用,类似下面WORD wHigh = 2;WORD wLow = 2;WORD wAll = ((wHigh << 8) | wLow);// 初始化只需要传入版本号,和WSADATA就可以了int reqErr = ::WSAStartup(wVersionRequested, &wsaData);if (reqErr != 0){printf("加载请求指定版本的windows socket api DLL 失败");return false;}/* Confirm that the WinSock DLL supports 2.2.*//* Note that if the DLL supports versions greater *//* than 2.2 in addition to 2.2, it will still return *//* 2.2 in wVersion since that is the version we *//* requested. */if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {/* Tell the user that we could not find a usable *//* WinSock DLL. */printf("Could not find a usable version of Winsock.dll\n");::WSACleanup();return false;}else{printf("The Winsock 2.2 dll was found okay\n");return true;}
}static void ReleaseWSAData()
{::WSACleanup();
}int main()
{int nLen = sizeof(SOCKADDR_IN);if (!LoadWSAData(wsaData)){fprintf(stderr, "Load WSADTATA failed!\n");return 0;}sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // 协议族,socket类型,具体协议if (INVALID_SOCKET == sClient){ReleaseWSAData();printf("Get Socket Error: INVALID_SOCKET.\n");return 0;}CheckBuffer(sClient);memset(&server, 0, sizeof(SOCKADDR_IN));server.sin_family = AF_INET;server.sin_addr.S_un.S_addr = inet_addr(IP_ADDRESS);server.sin_port = htons(PORT);int nConnect = connect(sClient, (struct sockaddr *)&server, sizeof(SOCKADDR_IN));if (SOCKET_ERROR == nConnect){printf("Socket connnect Error:%d\n", WSAGetLastError());closesocket(sClient);ReleaseWSAData();return 0;}int messageLength = 0;while (TRUE){memset(szMessage, 0, sizeof(szMessage));printf("请输入发送到服务器的消息:");fgets(szMessage, sizeof(szMessage), stdin);messageLength = strlen(szMessage);if (messageLength < 2){fprintf(stderr, "你没有输入消息!\n");continue;}int retCode = send(sClient, szMessage, strlen(szMessage), 0);// strlen求得的字符串长度不包含'\0'if (SOCKET_ERROR == retCode)printf("Send Copy data kernel buffer is too small or network shutdown!\n");if (retCode == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET){fprintf(stderr, "Server has disconneted, send data to server failed!\n");break;}else if (retCode == SOCKET_ERROR){printf("Send data to Server failed!\n");break;}if (retCode != SOCKET_ERROR)printf("Send data to Server finished.\n");int nRecvRes = recv(sClient, szMessage, MSGSIZE, 0);if (nRecvRes > 0){szMessage[nRecvRes] = '\0';printf("接收到服务器发来的消息 : %s\n", szMessage);}else if (nRecvRes == 0 || (nRecvRes == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET)){printf("Server Connection Close.\n");break;}else if (nRecvRes == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK){fprintf(stdout, "非阻塞类型返回\n");continue;}else{printf("Unknow recv error code: %d\n", WSAGetLastError());break;}}closesocket(sClient);ReleaseWSAData();return 0;
}
相关文章:

游戏开发:js实现简单的板球游戏
js实现简单的板球游戏大家好,本次我们来使用js来实现一个简单的板球游戏。截图如下:首先,设计页面代码,页面代码很简单,因为整个几乎是使用js编写的,页面几乎没有代码,如下:<!DOC…

SLAM精度测评——EVO进阶
1. 基本概念 1.1 Umeyama算法 ATE: evo_ape tum state_groundtruth_estimate0/data.tum orb2/CameraTrajectory.txt -r trans_part -va --plot --plot_mode xy --save_results /home/sun/evo/v1_01_easy/orb2/ate.zip RPE: evo_rpe tum state_groun…

python读取图片并且显示
使用python-opencv读取图片,利用opencv或matplotlib显示图片。 # -*- coding: utf-8 -*-import numpy as np from matplotlib import pyplot as plt #import urllib import cv2def load_image1(file):# Load an color image in grayscaleimg cv2.imread(file,0)cv…

shiro认证
shiro权限认证: 具体的认证流程是这样的: 一般流程: 通过.ini的文件来初始化工厂,.ini的文件的好处是可以创建多个组,而.properties的文件只能创建一组。 系统默认有shiro.ini的文件,但是一般我们是自定义数…

小猿圈Linux基础面试题,看看你能答对几道?
最近身边的很多朋友都在学习linux,从最开始的安装软件都需要百度一天的他们,现在已经成长为了,不需要百度就可以把自己弄懵圈的了,接下来的几天小猿圈linux老师会为大家准备一些实用的linux技巧分析给大家,希望对你有所…

ORB-SLAM2 论文翻译
https://ug98gs7tbw.feishu.cn/docs/doccnKKOWAjkKv7AzAiEvbnM3Tf

mxnet教程1
import mxnet as mx #%matplotlib inline import os import subprocess import numpy as np import matplotlib.pyplot as plt import tarfileimport warnings warnings.filterwarnings("ignore", categoryDeprecationWarning)# 从内存中读取数据 def test1():data …

番外:Spring MVC环境搭建和Mybatis配置避坑篇
2019独角兽企业重金招聘Python工程师标准>>> web.xml引入对spring mvc的支持; spring-mvc配置spring-mvc; spring-mybatis配置mybatis支持,并指名mapper文件的位置; mybaits-config配置mybatis; jdbc.prope…

50个云终端只需一台服务器是怎么一回事
看到这个标题也许有人会说50个云终端只需要一台服务器这应该是不可能的吧,即使是真的那这个服务器的配置和价格应该也要非常高的吧。但是如果有人和你说50个云终端只需要一台中等配置和价格的服务器就可以的呢。而且这50个用户桌面都可以正常的使用不会出现卡顿等现…

SLAM学习,小白入门到殿堂级大牛资料整理
总结一下我接触过的SLAM算法吧,主要集中在visual slam: 特征法: ORB SLAM https://github.com/raulmur/ORB_SLAM2优势: 在静态环境下定位准确,稳定, 单目和双目版本都可以达到实时(高于10frames/s)。代码可读性强,易扩展, 网上也有实现和imu融合的版本。 劣势:建的地图…

python解析json
“data.json”文件内容如下: {"id":"1220562","alt":"http:\/\/book.douban.com\/book\/1220562","rating":{"max":10, "average":"7.0", "numRaters":282, "min…

8.改进应用程序
2019独角兽企业重金招聘Python工程师标准>>> ##8.1数字格式设置(storyboard) ##8.1.2可选类型拆封 import Cocoa extension Double{var dollars : String{let formatter : NumberFormatter NumberFormatter()//NSNumberFormatter弃用var re…

小猿圈Linux学习-Linux种搜索的命令
做Linux工程师的每天都不能少的工作就是搜索文件,这是他们的日常活动,很繁琐很枯燥,所以我们就需要知道一些搜索的命令,这些命令更高效更快捷,今天小猿圈就给大家分享4个可以搜索的Linux命令。。 方法 1:使…
SURF与SIFT比较分析
opencv3.2 SURF实现特征点匹配 opencv3.2中SurfFeatureDetector、SurfDescriptorExtractor、BruteForceMatcher这三个的使用方法已经和原先2.4版本前不一样了。 使用方法示例如下: Ptr<SURF> detector SURF::create(minHessian);detector->detect(img_1…

python文件和目录
# -*- coding: utf-8 -*-import osdef printFile(rootDir):allFiles os.listdir(rootDir) #列出文件夹下所有文件和目录for i in range(0, len(allFiles)):# print(rootDir allFiles[i])path os.path.join(rootDir, allFiles[i])if not os.path.isfile(path):print(path, &q…

你不怕他离职吗?
图片来自“wikiart” 这是我同事在晚上11点多跟我聊微信时问起的一个问题,我觉得这个问题还是挺有代表性的,所以我还是决定就这个问题展开聊聊我对这句话的看法。 我同事之所以这么说,是因为他的组员,也就是问题中的那个他&#x…

tensorflow 1
import tensorflow as tf import numpy as np import matplotlib.pylab as pltdef tfDemo1():#create datax_data np.random.rand(100).astype(np.float32)y_data x_data * 0.1 0.3#create tensorflow structureWeightstf.Variable(tf.random_uniform([1],-1.0,1.0)) #一维&…

SLAM资源整理
资源整理 浙大3D Group VINS orbslam2 orbslam2 video study https://www.bilibili.com/video/BV1bK4y197kB/?spm_id_fromautoNext orbslam2 csdn https://blog.csdn.net/ncepu_chen/category_9874746.html https://www.zhihu.com/column/c_1114864226103037952 https:…

Golang微服务开发实践
github: github.com/yun-mu/Micr… 微服务概念学习:可参考 Nginx 的微服务文章 微服务最佳实践:可参考 微服务最佳实践 demo 简介 服务: consignment-service(货运服务)user-service(用户服务)l…

Linux ssh/scp/docker学习
文章目录Linux ssh/scp/docker使用学习1. ssh 登录2. scp传输文件3. docker4. git checkout 替换指定分支的单个文件Linux ssh/scp/docker使用学习 1. ssh 登录 sudo ssh fireflyip (登录账号密码) scp -r company/data_depthfill/ firefly192.168.105.6:/tmp/ 2…

tensorflow mnist 1
import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data import keras.backend.tensorflow_backend as KTFdef add_layer(inputs,in_size,out_size,activation_functionNone):#Weights是一个矩阵,[行,列]为[in_size,out_s…

framework7使用笔记
2019独角兽企业重金招聘Python工程师标准>>> myApp.addView(.view-main, {}); 以上这句代码一定要添加 ,否则链接的页面不能正常加载 --------------------------------------------- 如果初始化时定义了preprocess,则页面上链接的自动加载将…

Linux:检查当前运行级别的五种方法
2019独角兽企业重金招聘Python工程师标准>>> 运行级就是Linux操作系统当前正在运行的功能级别。存在七个运行级别,编号从0到6。系统可以引导到任何给定的运行级别。运行级别由数字标识。每个运行级别指定不同的系统配置,并允许访问不同的进程…

概率机器人资料整理
机器人算法仿真 https://atsushisakai.github.io/PythonRobotics/ 最大熵对应的概率分布及其优化推导 https://www.cnblogs.com/yychi/p/9401807.html 矩阵计算网址 http://www.yunsuan.info/matrixcomputations/index.html

LLVM官方文档翻译---- LLVM原子指令与并发指引
英文原文地址:http://llvm.org/docs/Atomics.html 译文原文地址:http://blog.csdn.net/wuhui_gdnt/article/details/52485591 注:该文章转载已经得到译者授权。 --------------------------------------------------------------------------…

matplotlib画图
import matplotlib.pyplot as plt import numpy as npdef test1():# 从[-1,1]中等距去50个数作为x的取值x np.linspace(-1, 1, 50)print(x)y 2*x 1y1 2**x 1# 第一个是横坐标的值,第二个是纵坐标的值plt.plot(x, y)plt.plot(x, y1)# 必要方法,用于将…

学习新对象字面量语法
目标 使用简写属性名称使用简写方法名称使用计算属性名称问题 哪些部分是冗余的? const person{name:name,address:address,sayHello:function(){/*......*/},sayName:function(){/*......*/}sayAddress:function(){/*......*/}} 复制代码简写属性名称 //ES5 const message{te…

ORB-SLAM2代码/流程详解
ORB-SLAM2代码详解 文章目录ORB-SLAM2代码详解1. ORB-SLAM2代码详解01_ORB-SLAM2代码运行流程1 运行官方Demo1.2. 阅读代码之前你应该知道的事情1.2.1 变量命名规则1.3 理解多线程1.3.1 为什么要使用多线程?1.3.2 多线程中的锁1.4 SLAM主类System1.4.1 System类是ORB-SLAM2系统…

VS2010 CUDA 5.5 Win7 64位配置以及项目创建配置
一.安装CUDA5.5以及配置VS助手 1、安装之前必须确认自己电脑的GPU支持CUDA。在设备管理器中找到显示适配器(Display adapters),找到自己电脑的显卡型号,如果包含在http://www.nvidia.com/object/cuda_gpus.html的列表中,说明支持…

HTC VIVE SDK 中的例子 hellovr_opengl 程序流程分析
最近Vive的VR头盔设备很火,恰逢项目需求,所以对 SDK 中的例子 hellovr_opengl 做了比较细致的代码分析,先将流程图绘制如下,便于大家理解。 在ViVe头盔中实现立体效果的技术核心: 如果要外挂Vive的VR设备实现立体效果&…