O_NONBLOCK、select、keep alive接続、およびHTTPなどのソケットを使用しています。
各サーバー接続とクライアント側は、完全なメッセージが受信されるまで、バッファを使用して送信されたすべてのデータを取得します
作業方法:
クライアントはデータ「A」を送信
しますクライアントはサーバーから応答を受信しようとします
サーバーは受信しますがすぐには応答しません
クライアントはタイムアウトを取得し
ますサーバーは応答「A」を送信します(ただしクライアントは今は受信しません)
別のリクエスト:
クライアントはデータ「B」
を送信しますサーバーは応答「B」を送信し
ますクライアントは「B」のみの代わりに「AB」応答を受信します
問題は、クライアントが以前のバッファメッセージを受信することです
以下のソースコード:
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;
}
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);
}
クライアント側のコードは、タイムアウト付きの単純なrecv送信です
解決する方法はありますか?