运行效果:

程序:

// TcpServer.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <iostream>
#include <WinSock2.h>
#include <Windows.h>
#include <vector>
#include <algorithm>
using namespace std;
//包含库
#pragma comment(lib, "ws2_32.lib")
//发送最大字节数
#define MAXDATASIZE 100
#define BACKLOG 100
const int SERVERPORT = ; //连接数
static int connum; //客户端连接线程函数
DWORD WINAPI qtPingServerThreadFunc(LPVOID lpThreadParameter);
//客户连接socket数组
vector<SOCKET> client_fd; int _tmain(int argc, _TCHAR* argv[])
{
int err; SOCKET sockfd; struct sockaddr_in local_addr;
struct sockaddr_in remote_addr; WORD wRequestVersion;
WSADATA wsadata;
wRequestVersion = MAKEWORD(, );
//启动socket服务
err = WSAStartup(wRequestVersion, &wsadata);
if ( != err)
{
printf("Socket Error!\n");
return ;
} if (LOBYTE(wsadata.wVersion) != || HIBYTE(wsadata.wVersion) != )
{
WSACleanup();
printf("Version Wrong!\n");
return ;
}
//创建socket
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (INVALID_SOCKET == sockfd)
{
printf("Socket Create Failed!\n");
return ;
}
else
{
printf("Socket Create Success!\n");
}
//定义服务器地址信息
local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(SERVERPORT);
//INADDR_ANY自动绑定地址
local_addr.sin_addr.s_addr = INADDR_ANY;//inet_addr("172.16.254.212");
memset(&(local_addr.sin_zero), , );
//绑定socket到本机地址
if (bind(sockfd, (struct sockaddr *)&local_addr, sizeof(struct sockaddr)) == -)
{
printf("bind wrong!\n");
return ;
}
else
{
printf("bind success!\n");
} int n = ;
unsigned long ul = ;
while ()
{
//主线程监听
if (listen(sockfd, BACKLOG) != -)
{
printf("Listening...\n"); int sin_size = sizeof(struct sockaddr_in);
//取出连接的客户端socket
SOCKET sock = accept(sockfd, (struct sockaddr *)&remote_addr, &sin_size);
//设置socket为非阻塞
ioctlsocket(sock,FIONBIO,(unsigned long *)&ul);// vector<SOCKET>::iterator itr_end = client_fd.end();
vector<SOCKET>::iterator itr = find(client_fd.begin(), itr_end, sock);
if (itr == itr_end)
{
client_fd.push_back(sock);
printf("receive a connection from %s\n", inet_ntoa(remote_addr.sin_addr));
connum++; printf("当前连接数:%d\n", connum);
} DWORD dwPingThreadID;
//创建新线程处理该客户socket连接
HANDLE hPingHandle = CreateThread(, , qtPingServerThreadFunc, (LPVOID)sock, , &dwPingThreadID);
}
Sleep();
} for (int i = ; i < client_fd.size(); i++)
{
closesocket(client_fd[i]);
}
client_fd.clear();
WSACleanup();
return ;
} DWORD WINAPI qtPingServerThreadFunc(LPVOID lpThreadParameter)
{
SOCKET sock = (SOCKET)lpThreadParameter; int recvbytes;
BYTE buf[MAXDATASIZE]; while ()
{
//接收数据
recvbytes = recv(sock, (char *)buf, MAXDATASIZE, );
//接收到的数据长度为0,则表示客户端主动断开连接
if (recvbytes == )
{
printf("disconnect!\n");
vector<SOCKET>::iterator itr_end = client_fd.end();
vector<SOCKET>::iterator itr = find(client_fd.begin(), itr_end, sock);
if (itr != itr_end)
{
client_fd.erase(itr);
}
connum--;
printf("当前连接数:%d\n", connum);
return ;
}
//接收信息,群发给所有客户端
else if ((recvbytes) != -)
{
buf[recvbytes] = '\0';
printf("Received: %s\n", buf);
BYTE * head;
head = buf; for (int i = ; i < client_fd.size(); i++)
{
send(client_fd[i], (char *)buf, sizeof(buf), );
}
}
Sleep();
}
return ;
}

WinSockAPI多线程服务器的更多相关文章

  1. 【LINUX/UNIX网络编程】之简单多线程服务器(多人群聊系统)

    RT,Linux下使用c实现的多线程服务器.这个真是简单的不能再简单的了,有写的不好的地方,还希望大神轻拍.(>﹏<) 本学期Linux.unix网络编程的第四个作业. 先上实验要求: [ ...

  2. 基于事件的 NIO 多线程服务器--转载

    JDK1.4 的 NIO 有效解决了原有流式 IO 存在的线程开销的问题,在 NIO 中使用多线程,主要目的已不是为了应对每个客户端请求而分配独立的服务线程,而是通过多线程充分使用用多个 CPU 的处 ...

  3. C# TCP多线程服务器示例

    前言 之前一直很少接触多线程这块.这次项目中刚好用到了网络编程TCP这块,做一个服务端,需要使用到多线程,所以记录下过程.希望可以帮到自己的同时能给别人带来一点点收获- 关于TCP的介绍就不多讲,神马 ...

  4. UDP和多线程服务器

    UDP: UDP是数据报文传输协议,这个传输协议比较野蛮,发送端不需要理会接收端是否存在,直接就发送数据,不会像TCP协议一样建立连接.如果接收端不存在的话,发送的数据就会丢失,UDP协议不会去理会数 ...

  5. Java如何创建多线程服务器?

    在Java编程中,如何创建多线程服务器? 以下示例演示如何使用ServerSocket类的MultiThreadServer(socketname)方法和Socket类的ssock.accept()方 ...

  6. 基于多进程和基于多线程服务器的优缺点及nginx服务器的启动过程

    基于多进程服务器的优点: 1.由操作系统进行调度,运行比较稳定强壮 2.能够方便地通过操作系统进行监控和管理 例如对每个进程的内存变化状况,甚至某个进程处理什么web请求进行监控.同时可以通过给进程发 ...

  7. TCP粘包/拆包 ByteBuf和channel 如果没有Netty? 传统的多线程服务器,这个也是Apache处理请求的模式

    通俗地讲,Netty 能做什么? - 知乎 https://www.zhihu.com/question/24322387 谢邀.netty是一套在java NIO的基础上封装的便于用户开发网络应用程 ...

  8. 用Java实现多线程服务器程序

    一.Java中的服务器程序与多线程 在Java之前,没有一种主流编程语言能够提供对高级网络编程的固有支持.在其他语言环境中,实现网络程序往往需要深入依赖于操作平台的网络API的技术中去,而Java提供 ...

  9. Linux网络编程echo多线程服务器

    echo_server服务器多线程版本 #include <unistd.h> #include <stdlib.h> #include <stdio.h> #in ...

随机推荐

  1. Csdn账号如何注销?

    Csdn账号如何注销?   请在ios端app设置内注销 ios端注销在设置页面的底部左下角,andriod在2019.07月底更新,即可支持   文章来源:刘俊涛的博客 欢迎关注,有问题一起学习欢迎 ...

  2. shell命令:getevent和sendevent

    1.getevent 输出所有event设备的基本信息 输出格式: 设备名: 事件type 事件code 事件value 注意:这里的数字都是16进制. getevent -c 10 //输出10条信 ...

  3. js for (i=0;i<a.length;a[i++]=0) 中等于0怎么理解?

    js的问题for (i=0;i<a.length;a[i++]=0) 中等于0怎么理解? 很奇怪的一个for循环 竟然是将原来数组的数据全改为0

  4. js图片转base64编码

    let reader = new FileReader(); reader.readAsDataURL(file.raw); reader.onload = () => { let imageU ...

  5. centos7 更改ip

    http://blog.csdn.net/heimerdinger_feng/article/details/71171231 CentOS7在桥接模式下配置静态ip 原创 2017年05月04日 1 ...

  6. Futter基础组件之二

    一.线性布局之Row布局组件(以水平阵列显示其子级的小部件) 属性:Row({ TextDirection textDirection, 表示水平方向子组件的布局顺序(是从左往右还是从右往左),默认为 ...

  7. 重置mysql数据库root密码

    一. 在已知MYSQL数据库的ROOT用户密码的情况下,修改密码的方法:1,shell环境下:]#mysqladmin –u root –p password “新密码” 回车后要求输入旧密码2,my ...

  8. Centos7下 升级php5.4到7.1 yum安装

    1.查看当前 PHP 版本 php -v 查看当前 PHP 相关的安装包,删除之 yum list installed | grep php yum remove php yum remove php ...

  9. 【计算机】DMA原理1

    DMA原理:DMA(Direct Memory Access,直接内存存取) 是所有现代电脑的重要特色,它允许不同速度的硬件装置来沟通,而不需要依于 CPU 的大量中断负载.否则,CPU 需要从来源把 ...

  10. ML.NET 1

    ML.NET 示例:目录 ML.NET 示例中文版:https://github.com/feiyun0112/machinelearning-samples.zh-cn英文原版请访问:https:/ ...