Ich bin völlig neu in der Socket-Programmierung.Ich versuche zu verstehen, die verschiedenen Praktiken, wenn es um Socket-Programmierung und die Handhabung mehrerer Verbindungen. Ich habe die folgende Funktionalität also für erreicht.Handle einzelnen Server und mehrere Clients in C++
Server an mehrere Clients verbinden. c1, c2, c3 ...... cn.
Server sendet ein Zeitfenster zum Client.
Server zum Übertragen Nachricht an dem Client senden. (Übertragen
Nachricht in begrenzten Dauer)Client-Nachricht innerhalb eines begrenzten Zeitperiode senden
einmal ersten verbundene Client ist Zeit über Server senden Nachricht an nächste Client für die Übertragung von Nachrichten und so.
Hier ist mein Arbeitscode.
Server.cpp
#include "stdafx.h"
#pragma comment(lib,"ws2_32.lib")
#include <WinSock2.h>
#include <string>
#include <iostream>
#include<conio.h>
#define DEFAULT_NC_TIME 20
#define MAX_CLIENTS 2
SOCKET Connections[MAX_CLIENTS];
int TotalConnections = 0;
#include <vector>
#include<time.h>
void wait (int seconds)
{
clock_t endwait;
endwait = clock() + seconds * CLOCKS_PER_SEC ;
while (clock() < endwait) {}
}
void ClientHandlerThread(int index) //index = the index in the SOCKET Connections array
{
int bufferlength; //Holds the length of the message a client sent
while (true)
{
recv(Connections[index], (char*)&bufferlength, sizeof(int), NULL); //get buffer length
char * buffer = new char[bufferlength+1]; //Allocate buffer
buffer[bufferlength] = '\0';
recv(Connections[index], buffer, bufferlength, NULL); //get buffer message from client
std::cout << buffer << std::endl;
delete[] buffer;
}
}
void emitMessageToClient(int indexOfClient, int ts){
std::string buftest="You are ready to transmit Message.\n";
int size = buftest.size(); //Get size of message in bytes and store it in int size
send(Connections[indexOfClient], (char*)&ts, sizeof(int), NULL); //send Timeslot Duration to the client i
send(Connections[indexOfClient], (char*)&size, sizeof(int), NULL); //send Size of message
send(Connections[indexOfClient], buftest.c_str(), buftest.size(), NULL); //send Message
}
int main()
{
//Winsock Startup
WSAData wsaData;
WORD DllVersion = MAKEWORD(2, 1);
if (WSAStartup(DllVersion, &wsaData) != 0)
{
MessageBoxA(NULL, "WinSock startup failed", "Error", MB_OK | MB_ICONERROR);
return 0;
}
SOCKADDR_IN addr;
int addrlen = sizeof(addr);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(1111);
addr.sin_family = AF_INET;
SOCKET sListen = socket(AF_INET, SOCK_STREAM, NULL);
bind(sListen, (SOCKADDR*)&addr, sizeof(addr));
listen(sListen, SOMAXCONN);
SOCKET newConnection; //Socket to hold the client's connection
int ConnectionCounter = 0; //# of client connections
for (int i = 0; i < MAX_CLIENTS; i++)
{
newConnection = accept(sListen, (SOCKADDR*)&addr, &addrlen);
if (newConnection == 0)
{
std::cout << "Failed to accept the client's connection." << std::endl;
}
else
{
std::cout << "Client "<<i<<" Connected!" << std::endl;
Connections[i] = newConnection;
TotalConnections += 1; //Increment total # of clients that have connected
}
}
int ts = DEFAULT_NC_TIME/(TotalConnections + 1); // caculating time slot for each of connected node including server
std::cout<<"\nPress any key to start transmission: ";
getche();
for(int i= 0; i < TotalConnections; i++){
emitMessageToClient(i, ts);
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ClientHandlerThread, (LPVOID)(i), NULL, NULL);
wait(ts);
if(i == (TotalConnections - 1)){
i = 0;
}
}
system("pause");
return 0;
}
Client.cpp
#include "stdafx.h"
#pragma comment(lib,"ws2_32.lib") //Required for WinSock
#include <WinSock2.h> //For win sockets
#include <string> //For std::string
#include <iostream> //For std::cout, std::endl, std::cin.getline
#include <time.h>
#include <vector>
#include <conio.h>
SOCKET Connection;//This client's connection to the server
void wait (int seconds)
{
clock_t endwait;
endwait = clock() + seconds * CLOCKS_PER_SEC ;
while (clock() < endwait) {}
}
void ClientThread()
{
int bufferlength; //Holds the length of the message we are receiving
int ts; // holds timeslot duration for this client
while (true)
{
recv(Connection, (char*)&ts, sizeof(int), NULL); //receive timeslot
recv(Connection, (char*)&bufferlength, sizeof(int), NULL); //receive bufferlength
char * buffer = new char[bufferlength+1];
buffer[bufferlength] = '\0';
recv(Connection, buffer, bufferlength, NULL);
std::cout << buffer << std::endl; //print out buffer
std::string userinput; //holds the user's chat message
for (int n= ts; n>0; n--)
{
userinput = "First client sending message...";
int bufferlength = userinput.size(); //Find buffer length
send(Connection, (char*)&bufferlength, sizeof(int), NULL); //Send length of buffer
send(Connection, userinput.c_str(), bufferlength, NULL); //Send buffer
wait (1);
}
delete[] buffer; //Deallocate buffer
}
}
int main()
{
//Winsock Startup
WSAData wsaData;
WORD DllVersion = MAKEWORD(2, 1);
if (WSAStartup(DllVersion, &wsaData) != 0)
{
MessageBoxA(NULL, "Winsock startup failed", "Error", MB_OK | MB_ICONERROR);
return 0;
}
SOCKADDR_IN addr;
int sizeofaddr = sizeof(addr);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(1111);
addr.sin_family = AF_INET;
Connection = socket(AF_INET, SOCK_STREAM, NULL);
if (connect(Connection, (SOCKADDR*)&addr, sizeofaddr) != 0)
{
MessageBoxA(NULL, "Failed to Connect", "Error", MB_OK | MB_ICONERROR);
return 0; //Failed to Connect
}
std::cout << "Connected!" << std::endl;
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ClientThread, NULL, NULL, NULL);
getche();
return 0;
}
einmal Server senden Nachricht an alle seine angeschlossenen clients.Server will Nachricht senden wieder zu seinem Erste Client Nachricht erneut senden (zyklisch)
Problem
Wie kann ich, wenn Server reden alle seine Kunden c1, c2, c3 bis Cn erreichen und wieder zu seinem ersten Client C1 sprechen. (Zyklisch) die ich verwendet habe dieses Kontroll
if(i == (TotalConnections - 1)){
i = 0;
}
aber das Programm zum Absturz bringen.
Versuchen Sie es mit 'threads' – daemon7osh
Verwenden Sie ein Thread-Pool mit einer Jobwarteschlange. –
@ daemon7osh Der obige Code funktioniert gut. wenn ich es benutze, überprüfe es, crash das Programm.Ich denke auf der Client-Seite CreateThread-Funktion nicht effizient behandeln – Ali