程序说明
本程序为博主原创,转载请注明出处。
适用于windows系统。
程序功能
本程序实现了
多线程处理多客户端:
根据ip地址发送数据给客户端:
各客户端互不影响:
程序所使用类
winsock2.h:windows中socket网络编程类;
thread:c++11中定义的多线程处理类;
time.h:时间类,调用系统时间。
具体可自行搜索。
server端程序
#include"pch.h"
#include <winsock2.h>
#include"iostream"
#include"thread"
#include"time.h"
using namespace std;
#pragma comment(lib,"ws2_32.lib")
#define Sock(a,b) SOCKET a##b
static int num = -1;
static SOCKET temporary[100];
static sockaddr_in transmit[100];
class server
{
protected:
int Err;
WSADATA wfhdata;//windows返回版本信息
SOCKET sServer;
SOCKET sClient;
char buf[64];
friend class IO;
public:
int begin(int port)
{
if (WSAStartup(MAKEWORD(2, 2), &wfhdata) != 0)//加载socket库、0为真
{
cout << "加载失败:" << endl << "退出";
return -1;
}
sServer = socket(AF_INET, SOCK_STREAM, 0);//创建监听套接字
if (sServer == INVALID_SOCKET)//判断创建是否成功
{
cout << "scoket失败:" << endl << "退出:";
WSACleanup();
return -2;
}
int mode = 1;
Err = ioctlsocket(sServer, FIONBIO, (u_long*)& mode);//非阻塞
if (Err == SOCKET_ERROR)
{
cout << "非阻塞失败:" << endl << "退出:";
WSACleanup();
return -3;
}
sockaddr_in address;//初始化地址,端口
address.sin_family = AF_INET;
address.sin_port = htons(port);
address.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
Err = ::bind(sServer, (const struct sockaddr*) & address, sizeof(address));//绑定ip
if (Err == SOCKET_ERROR)
{
cout << "绑定失败:" << endl << "退出:";
closesocket(sServer);
WSACleanup();
return -4;
}
Err = listen(sServer, 99);//监听网络
if (Err == SOCKET_ERROR)
{
cout << "监听失败:" << endl << "退出:";
closesocket(sServer);
WSACleanup();
return -5;
}
cout << "服务器已打开:" << endl;
}
int process()//多进程
{
while (true)
{
sockaddr_in addclient;
int numberaddclient = sizeof(addclient);
sClient = accept(sServer, (sockaddr*)& addclient, (int*)& numberaddclient);
if (INVALID_SOCKET == sClient)
{
int err = WSAGetLastError();
if (err == WSAEWOULDBLOCK)
{
Sleep(1000);
continue;
}
else
{
cout << "客服端连接失败:" << endl << "退出:";
return -6;
}
}
send(sClient, "this is 117.78.8.97 server.\nplease enter instructions.", strlen("this is 117.78.8.97 server.\nplease enter instructions."), 0);
num++;
temporary[num] = sClient;
transmit[num] = addclient;
}
}
int collect_thread()
{
thread pro(&server::process, this);
pro.detach();
thread Count(&server::count, this, temporary, transmit);
Count.detach();
}
int count(SOCKET i[], sockaddr_in ip[])
{
char* location;
int port;
int Port;
int retval;
char addr[16];
char Write[512];
while (true)
{
Sleep(1000);
if (num > -1)
{
cout << "please enter the delivery address:\n";
cin >> addr;
cout << "please enter the delivery port:\n";
cin >> port;
for (int repeat = 0; repeat <= num;)
{
sockaddr_in buf = ip[repeat];
location = inet_ntoa(buf.sin_addr);
Port = ntohs(buf.sin_port);
if (strcmp(location, addr) == 0)
{
if (Port == port)
{
while (true)
{
cout << "please enter delivery value or enter “quit”sign out :\n";
cin >> Write;
if (strcmp(Write, "quit") == 0)
{
break;
}
else
{
retval = send(i[repeat], Write, strlen(Write), 0);
if (retval <= 0)
{
int err = WSAGetLastError();
if (err == WSAEWOULDBLOCK)
{
Sleep(200);
continue;
}
else
{
cout << "client no connect!\n";
closesocket(i[repeat]);
}
}
cout << "delivery success:\n";
}
}
}
else
{
repeat++;
continue;
}
}
repeat++;
}
cout << "client no connect!\n";
}
}
}
};
class IO
{
public:
int Err;
char Buf[512];
char Write[512];
int retval;
SOCKET moddle;
time_t t = time(0);
char Stime[64];
sockaddr_in display;
int Out(SOCKET i, sockaddr_in ip)
{
display = ip;
moddle = i;
thread w(&IO::R, this);
w.detach();
}
int R()//先读再写
{
while (true)
{
ZeroMemory(Buf, 512);
retval = recv(moddle, Buf, 512, 0);
if (0 >= retval)
{
Err = WSAGetLastError();
if (Err == WSAEWOULDBLOCK)
{
Sleep(200);
continue;
}
else
{
cout << "client disconnect:\n";
closesocket(moddle);
return -7;
}
}
strftime(Stime, sizeof(Stime), "%Y/%m/%d %X %A 本年第%j天 [时区:%z]", localtime(&t));
cout << Stime << "[客户端ip]:" << inet_ntoa(display.sin_addr) << " 进程: [" << ntohs(display.sin_port) << "] read: " << Buf << endl;
send(moddle, "你的消息已收到:\n", strlen("你的消息已收到:\n"), 0);
}
}
int W()
{
while (true)
{
cin >> Write;
retval = send(moddle, Write, strlen(Write), 0);
if (retval <= 0)
{
int err = WSAGetLastError();
if (err == WSAEWOULDBLOCK)
{
Sleep(200);
continue;
}
else
{
cout << "网络中断";
closesocket(moddle);
return -9;
}
}
}
}
};
int main()
{
server ser;
ser.begin(33);
ser.collect_thread();
IO out[100];
int i = 0;
while (num != -2)
{
if (num >= i)
{
out[i].Out(temporary[i], transmit[i]);
i++;
}
Sleep(500);
}
}
最后
程序到此也就结束了,欢迎大家评论留言改正博主的错误之处,不胜感激。