代码拉取完成,页面将自动刷新
#include "client.hpp"
#ifndef _WIN32
#include <arpa/inet.h>
#include <netinet/in.h>
#include<fcntl.h>
#include<string.h>
#include <unistd.h>
#endif
#include<stdio.h>
#include<string>
#include<errno.h>
bool Client::emptysendback(Client*,void*){return true;}
Client::Client(DataPack defaultpack,TimeoutCallback timeout,void* timeoutarg,
time_t maxtime):maxtime(maxtime),pos(0),size(0),sendcount(0),recvcount(0),
_socket(-1),timeout(timeout),timeoutarg(timeoutarg),defaultpack(defaultpack),
sendpos(0),recvpos(0){}
Client::~Client(){
if(_socket!=-1){
#ifdef _WIN32
closesocket(_socket);
#else
close(_socket);
#endif
}
}
size_t Client::getdata(char* buffer,size_t length){
if(pos!=size){
_thread_begin_recv:
auto got=std::min(size-pos,length-recvpos);
memcpy(buffer+recvpos,cache+pos,got);
pos+=got;
return got;
}
if(length>=CACHESIZE){
auto back=recv(_socket,buffer+recvpos,length-recvpos,0);
if(back>0)return back;
return -1;
}
auto back=recv(_socket,cache,CACHESIZE,0);
if(back>0){
pos=0;
size=back;
goto _thread_begin_recv;
}
return -1;
}
#ifdef _WIN32
int Client::connecthost(const char* address,unsigned int port){
std::string p(std::to_string(port));
struct addrinfo hints;
struct addrinfo *result=NULL;
memset(&hints,0,sizeof(hints));
hints.ai_family=AF_INET;
hints.ai_socktype=SOCK_STREAM;
hints.ai_protocol=IPPROTO_TCP;
hints.ai_flags=AI_PASSIVE;
auto res=getaddrinfo(0,p.c_str(),&hints,&result);
if(res){
printf("getaddrinfo error: %d\n",res);
return -1;
}
auto s=socket(result->ai_family,result->ai_socktype,result->ai_protocol);
if(s==INVALID_SOCKET){
printf("socket create error\n");
return -1;
}
static unsigned long NBMODE=1;
ioctlsocket(s,FIONBIO,&NBMODE);
if(_socket!=-1)closesocket(_socket);
_socket=s;
struct sockaddr_in addr{
.sin_family=AF_INET,
.sin_port=htons(port)
};
addr.sin_addr.s_addr=inet_addr(address);
connect(s,(struct sockaddr*)&addr,sizeof(sockaddr_in));
recordtime=time(nullptr);
return 0;
}
#else
int Client::connecthost(const char* address,unsigned int port){
int s=socket(AF_INET,SOCK_STREAM|SOCK_NONBLOCK,IPPROTO_TCP);
if(s==-1){
printf("socket create error:%d\n",errno);
return -1;
}
if(_socket!=-1)close(_socket);
_socket=s;
struct sockaddr_in addr{
.sin_family=AF_INET,
.sin_port=htons(port)
};
addr.sin_addr.s_addr=inet_addr(address);
connect(s,(struct sockaddr*)&addr,sizeof(sockaddr_in));
recordtime=time(nullptr);
return 0;
}
#endif
void Client::update(){
auto& pendingrecv=this->pendingrecv;
auto precv=pendingrecv.begin();
auto curtime=time(nullptr);
if(precv!=pendingrecv.end()){
auto got=getdata(precv->src,precv->size);
if(got!=-1){
recvpos+=got;
recordtime=curtime;
if(recvpos==precv->size){
recvpos=0;
if(precv->callback(this,precv->arg)){
pendingrecv.pop_front();
recvcount--;
}
}
}
else if(curtime-recordtime>=maxtime){
timeout(this,timeoutarg);
pendingsend.clear();
pendingrecv.clear();
return;
}
}
auto& pendingsend=this->pendingsend;
auto psend=pendingsend.begin();
auto& pack=this->defaultpack;
auto size=pack.size;
if(psend!=pendingsend.end()){
auto back=send(_socket,psend->src+sendpos,psend->size-sendpos,0);
if(back>0){
recordtime=curtime;
sendpos+=back;
if(sendpos==psend->size){
sendpos=0;
if(psend->callback(this,psend->arg)){
pendingsend.pop_front();
sendcount--;
}
}
}
else if(curtime-recordtime>=maxtime){
timeout(this,timeoutarg);
pendingsend.clear();
pendingrecv.clear();
return;
}
}
else if(size){
auto back=send(_socket,(char*)pack.src+sendpos,size-sendpos,0);
if(back>0){
recordtime=curtime;
sendpos+=back;
if(sendpos==size){
sendpos=0;
pack.callback(this,pack.arg);
}
}
else if(curtime-recordtime>=maxtime){
timeout(this,timeoutarg);
pendingsend.clear();
pendingrecv.clear();
return;
}
}
}
void Client::senddata(DataPack p){
if(!sendcount){
auto ret=send(_socket,p.src,p.size,0);
if(ret==p.size){if(p.callback(this,p.arg))return;}
else if(ret!=-1)sendpos=ret;
}
pendingsend.push_back(p);
sendcount++;
}
void Client::recvdata(DataPack p){
if(!recvcount){
auto ret=getdata(p.src,p.size);
if(ret==p.size){if(p.callback(this,p.arg))return;}
else if(ret!=-1)recvpos=ret;
}
pendingrecv.push_back(p);
recvcount++;
}
bool Client::openlib(){
#ifdef _WIN32
WSADATA wsaData;
auto res=WSAStartup(MAKEWORD(2,2),&wsaData);
if(res){
printf("WSA start error %d\n",res);
return false;
}
#endif
return true;
}
void Client::closelib(){
#ifdef _WIN32
WSACleanup();
#endif
}
size_t Client::getsent(){return sendpos;}
size_t Client::getrecv(){return recvpos;}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。