首先,我对 C++ 还是很陌生。我正在尝试编写一个 GNSS 互联网广播播客程序。基本上,当客户端登录并被接受时,我的程序将客户端请求的数据流源存储在客户端类中。我打算使用两个数组的索引号来匹配一个 Client 对象数组和一个 clientSockets 数组,但是尝试使用 Select() 检查非阻塞套接字会使事情变得复杂。我找到了一些实现 Select() 的示例,但我不确定如何从我用来接受来自 listenSocket 的连接的数组中跟踪原始 clientSocket。
class Client{
public:
std::string source;
std::string user; //stored in txt file as name:password
boolean connected;
int IndexNumber;
};
typedef struct _MYSOCKET_INFORMATION{
char Buffer[BUFFERSIZE];
WSABUF DataBuf;
SOCKET Socket;
DWORD SendBytes;
DWORD RecvBytes;
}SOCKET_INFORMATION, *LPSOCKET_INFORMATION;
// creates number of objects of this structure
LPSOCKET_INFORMATION SocketList[NUMBER_CLIENTS];
FD_SET Writer;
FD_SET Reader;
DWORD TotalSockets = 0;
DWORD Flags;
u_long NonBlock = 1;
timeval tv;
long tv_sec = 1;
long tv_usec = 0;
//intiate objects
Caster caster;
DataStream datastream[NUMBER_BASES]; //100 base stations max
Client client[NUMBER_CLIENTS];
SOCKET listenSocket;
SOCKET clientSocket[NUMBER_CLIENTS];
SOCKET serverSocket;
char recvArray[BUFFERSIZE];
using namespace std;
int main()
{
//initialize the Read and Write socket sets
FD_ZERO(&Reader);
FD_ZERO(&Writer);
//check for connection attempt
FD_SET(listenSocket, &Reader);
FD_SET(serverSocket, &Reader);
//set read and write state based on state of buffer
for( unsigned int i=0; i<TotalSockets; i++){
if( SocketList[i]->RecvBytes < SocketList[i]->SendBytes){
FD_SET(SocketList[i]->Socket,&Writer);
}
else{
FD_SET(SocketList[i]->Socket,&Reader);
}
}
//Select returns number of sockets ready to be read/writen
Total = select(0, &Reader, &Writer, NULL, &tv);
if(Total == SOCKET_ERROR){
printf("Error select function %d\n", WSAGetLastError());
return 1;
}
if( FD_ISSET(listenSocket, &Reader)){
Total--;
//set current client no
while(client[current].connected == true){
current++;
if(current >= NUMBER_CLIENTS){
current = 0;
count++;
if(count >= 2){//has cylcled twice all must be set to true, can add no more.
count =0;
printf("client limit reached.\n");
break;
}
}
}
clientSocket[current] = accept(listenSocket, NULL, NULL); //setup client connection for further use
if( clientSocket[current] != INVALID_SOCKET){
//set new client to non blocking
check = ioctlsocket(clientSocket[current], FIONBIO, &NonBlock);
if( check == SOCKET_ERROR){
printf("Error setting client to nonblocking mode. %d.\n", WSAGetLastError());
closesocket(clientSocket[current]);
continue;
}
else{
printf("Accepted client connection request \n");
//recieve data
check = recv(clientSocket[current], recvArray, BUFFERSIZE, 0);
if( check == SOCKET_ERROR){ //close connection if error
printf("error recieving login data. %d \n", WSAGetLastError());
closesocket(clientSocket[current]);
continue;
}
if( check == 0){//no data is recieved then client disconnected
printf("ERROR no data, client dsiconnected.\n");
closesocket(clientSocket[current]);
continue;
}
else{
for(int n=0; n<check +1 ; n++){ //must be request message for data per NTRIP 1.0
clientRequest << recvArray[n]; //place read char bytes into stringstream object for parsing.
}
//if request is good returns a client requested source, username, and true false for data send.
checkClientRequest(clientSocket[current], client[current].source, client[current].connected, client[current].user);
}
}
}
}//end of check client listen socket
for(unsigned int i=0; Total>0 && i<TotalSockets; i++){
LPSOCKET_INFORMATION SocketInfo = SocketList[i];
//check if client sends GGA string
if(FD_ISSET(SocketInfo->Socket, &Reader)){
Total--;
SocketInfo->DataBuf.buf = SocketInfo->Buffer;
SocketInfo->DataBuf.len = BUFFERSIZE;
Flags = 0;
SocketInfo->RecvBytes = sizeof(SocketInfo->DataBuf);
check = WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &(SocketInfo->RecvBytes), &Flags, NULL, NULL);
if( check == SOCKET_ERROR){
FreeSocketInformation(i); //shuts down client socket if socket error
continue;
}
else{
memcpy(recvArray, SocketInfo->DataBuf.buf, SocketInfo->RecvBytes +1);
//print data on screen change to sort lines
printf("%s \n", SocketInfo->DataBuf.buf);
}
}
它不仅限于此,但如何使用我的 clientSocket[] 跟踪结构 SocketInfo?