[英]Handle single server and multiple clients in c++
我對套接字編程完全陌生,我正在嘗試了解套接字編程和處理多個連接時的不同做法。 我已經實現了以下功能。
服務器連接到多個客戶端。 C1,C2,C3 ...... CN。
服務器發送一個時隙給客戶端。
服務器向客戶端發送消息以發送消息。
限時留言)
客戶在限定時間內發送消息
一旦第一個連接的客戶端通過服務器超時,則將消息發送到下一個客戶端以傳輸消息,依此類推。
這是我的工作代碼。
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;
}
服務器一旦向其所有連接的客戶端發送消息,服務器便希望再次向其第一個客戶端發送消息以再次發送消息。
問題
如果服務器將其所有客戶端c1,c2,c3與Cn對話並再次與其第一個客戶端C1對話,我該如何實現。(循環地)我使用了此檢查
if(i == (TotalConnections - 1)){
i = 0;
}
但它使程序崩潰。
通過將i
設置為0
您將創建一個無限循環,因為i
永遠不會變得足夠大而無法結束循環。
for(int i= 0; i < TotalConnections; i++) {
emitMessageToClient(i, ts);
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ClientHandlerThread, (LPVOID)(i), NULL, NULL);
wait(ts);
// This will create an infinite loop
if(i == (TotalConnections - 1))
{
i = 0;
}
}
您可以做的就是等待循環完成后重新訪問第一個連接:
for(int i= 0; i < TotalConnections; i++) {
emitMessageToClient(i, ts);
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ClientHandlerThread, (LPVOID)(i), NULL, NULL);
wait(ts);
}
// now the loop is over, revisit the first connection
// if it exists
if(TotalConnections > 0) {
emitMessageToClient(0, ts);
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ClientHandlerThread, (LPVOID)(0), NULL, NULL);
wait(ts);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.