Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sockets 在客户端获取服务器响应超时后,如何使服务器忽略从客户端发送的数据?_Sockets_Client Server - Fatal编程技术网

Sockets 在客户端获取服务器响应超时后,如何使服务器忽略从客户端发送的数据?

Sockets 在客户端获取服务器响应超时后,如何使服务器忽略从客户端发送的数据?,sockets,client-server,Sockets,Client Server,我正在使用socket和O_NONBLOCK、select、keep-alive连接以及类似HTTP的东西 每个服务器连接和客户端都使用一个缓冲区来获取所有发送的数据,直到收到完整的消息为止 如何工作: 客户端发送数据“A” 客户端尝试从服务器接收响应 服务器收到但不立即回复 客户端获取超时 服务器发送响应“A”(但客户端现在不接收) 另一项请求: 客户端发送数据“B” 服务器发送响应“B” 客户端接收“AB”响应,而不是仅接收“B” 问题是客户端接收到以前的缓冲区消息 源代码如下: Serve

我正在使用socket和O_NONBLOCK、select、keep-alive连接以及类似HTTP的东西

每个服务器连接和客户端都使用一个缓冲区来获取所有发送的数据,直到收到完整的消息为止

如何工作:

客户端发送数据“A”
客户端尝试从服务器接收响应
服务器收到但不立即回复
客户端获取超时
服务器发送响应“A”(但客户端现在不接收)

另一项请求:

客户端发送数据“B”
服务器发送响应“B”
客户端接收“AB”响应,而不是仅接收“B”

问题是客户端接收到以前的缓冲区消息

源代码如下:

Server.cpp基类:

bool Server::start()
{
    struct sockaddr_in client_addr;
    SOCKET client_socket, max_sock;
    Connection* conn;
    int addrlen = sizeof(struct sockaddr_in);
    std::list<Connection*>::iterator it, itr;
    int response;
    fd_set fdset, read_fds;

    max_sock = m_socket;
    FD_ZERO(&fdset);
    FD_SET(m_socket, &fdset);
    onStart();

    while(true)
    {
        // make a copy of set
        read_fds = fdset;
        // wait for read event
        response = select(max_sock + 1, &read_fds, NULL, NULL, NULL);
        if(response == -1)
            break;
        // check for new connections
        if(FD_ISSET(m_socket, &read_fds))
        {
            response--;
            // accept connections
            client_socket = accept(m_socket, (struct sockaddr*)&client_addr, &addrlen);
            if(client_socket != INVALID_SOCKET)
            {
                conn = new Connection(*this, client_socket, &client_addr);
                m_connections.push_front(conn);
                // add connection to set for wait for read event
                FD_SET(client_socket, &fdset);
                // allow select new sock from select funcion
                if(max_sock < client_socket)
                    max_sock = client_socket;
            }
        }
        // check for received data from clients
        it = m_connections.begin();
        while(it != m_connections.end() && response > 0)
        {
            conn = *it;
            // verify if connection can be readed
            if(FD_ISSET(conn->getSocket(), &read_fds))
            {
                response--;
                conn->receive();
                if(!conn->isConnected())
                {
                    FD_CLR(conn->getSocket(), &fdset);
                    // remove connection from list
                    itr = it;
                    it++;
                    m_connections.erase(itr);
                    delete conn;
                    continue;
                }
            }
            it++;
        }
    }
    onFinish(response >= 0);
    return response >= 0;
}
bool服务器::start()
{
客户端地址中的结构sockaddr\u;
SOCKET客户端\u SOCKET,max\u sock;
连接*连接;
int addrlen=sizeof(结构sockaddr_in);
std::list::iterator it,itr;
int响应;
fd_set fdset,read_fds;
max_sock=m_sock;
FD_零点(&fdset);
FD_集(m_插座和fdset);
onStart();
while(true)
{
//复印一套
read_fds=fdset;
//等待读取事件
response=select(max_sock+1,&read_fds,NULL,NULL,NULL);
如果(响应==-1)
打破
//检查是否有新的连接
if(FD_设置(m_插槽和读取fds))
{
答复--;
//接受连接
client_socket=accept(m_socket,(struct sockaddr*)和client_addr,&addrlen);
if(客户端\u套接字!=无效的\u套接字)
{
conn=新连接(*此连接、客户端\u套接字和客户端\u地址);
m_连接。向前推(连接);
//添加连接以设置等待读取事件
FD_集(客户端_套接字和fdset);
//允许从“选择”功能中选择新袜子
if(最大插座<客户端插座)
max_sock=客户端_socket;
}
}
//检查从客户端接收的数据
it=m_connections.begin();
while(it!=m_connections.end()&&response>0)
{
conn=*it;
//验证是否可以读取连接
if(FD_-ISSET(conn->getSocket(),&read_-fds))
{
答复--;
连接->接收();
如果(!conn->isConnected())
{
FD_CLR(conn->getSocket(),&fdset);
//从列表中删除连接
itr=it;
it++;
m_连接擦除(itr);
删除conn;
继续;
}
}
it++;
}
}
onFinish(响应>=0);
返回响应>=0;
}
main.cpp服务器实现:

void ClientConnection::onReceive(const void * data, size_t size)
{
    const char *str, *pos = NULL;
    HttpParser* p;

    buffer->write(data, size);
    do
    {
        str = (const char*)buffer->data();
        if(contentOffset == 0)
        {
            pos = strnstr(str, buffer->size(), "\r\n\r\n");
            if(pos != NULL)
            {
                contentOffset = pos - str + 4;
                p = new HttpParser((const char*)buffer->data(), contentOffset);
                contentLength = p->getContentLength(); 
                delete p;
            }
        }
        if(buffer->size() - contentOffset < contentLength || contentOffset == 0)
            return;
        proccessRequest();
        keepDataStartingOf(contentOffset + contentLength);
    }
    while(buffer->size() > 0);
}
void ClientConnection::onReceive(const void*数据,大小)
{
常量字符*str,*pos=NULL;
httpp;
缓冲区->写入(数据、大小);
做
{
str=(const char*)缓冲区->数据();
if(contentOffset==0)
{
pos=strnstr(str,buffer->size(),“\r\n\r\n”);
如果(位置!=NULL)
{
contentOffset=pos-str+4;
p=新的HttpParser((const char*)buffer->data(),contentOffset);
contentLength=p->getContentLength();
删除p;
}
}
如果(缓冲区->大小()-contentOffset大小()>0);
}
客户端代码是一个带有超时的简单recv发送


你知道怎么解决吗?

首先想到的是让客户端的超时足够大,这样客户端就不会超时,除非服务器真的死了。。。但我相信你已经想到了这一点

因此,假设这还不够好,下一步要尝试的是让客户端在发送每个请求时发送一个ID号。可以使用简单计数器生成ID号(例如,对于客户端的第一个请求,它用0标记请求,对于第二个请求,它用1标记请求,等等)。服务器在发送回复时,将包含与回复相同的ID号


当客户端收到回复时,它会将回复数据中的ID号与其计数器的当前值进行比较。如果两个数字相同,它将处理数据。如果不是,则忽略数据。瞧

有什么问题?尝试重新定相。@NikolaiNFetissov如果问题是客户端收到以前的响应,则使用代码添加的第二种方法。如果不存在其他解决方案,则将使用第二种方法。第一种方法不是好的解决方案,因为超过6秒(当前等待时间)等待对游戏的响应可能非常耗时。我想另一种方法是找出服务器响应时间过长的原因,并修复它,使其响应更快。。。