服务器和客户端之间的通信正常,但服务器不会将客户端消息转发给其他连接的客户端,而只转发给发件人。
我希望服务器通过将它们广播到所有客户端(如聊天系统)来对传入消息做出反应,但保留我的命令系统,而不是使用所有客户端,而是使用发件人。
以下是来源:
服务器
/*server*/
#define WIN32_LEAN_AND_MEAN
#include <iostream>
#include <string>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <process.h>
// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
#define PORT "3490"
#define SERVER "localhost"
#include <time.h>
WSADATA wsa;
SOCKET s , new_socket;
struct sockaddr_in server , client;
int c;
char *message;
std::string line;
DWORD WINAPI ProcessClient (LPVOID lpParameter)
{
SOCKET AcceptSocket = (SOCKET) lpParameter;
// Send and receive data.
int bytesSent;
int bytesRecv = SOCKET_ERROR;
char sendbuf[2000]="";
char sendbuf2[2000]="";
char recvbuf[2000]="";
char timebuf[128];
sprintf(sendbuf, "Hello, it's a test server at %s:%d (commands: 1, 2, exit)\n", SERVER, PORT);
bytesSent = send( AcceptSocket, sendbuf, strlen(sendbuf), 0);
if (bytesSent == SOCKET_ERROR)
{
printf( "Error at send hello: %ld\n", WSAGetLastError());
goto fin;
}
while (1)
{
_strtime( timebuf );
ZeroMemory (recvbuf, sizeof(recvbuf));
bytesRecv = recv( AcceptSocket, recvbuf, 32, 0);
printf( "%s Client said: %s\n", timebuf, recvbuf);
sprintf(sendbuf, "%s Client said: %s\n", timebuf, recvbuf);
bytesSent = send( AcceptSocket, sendbuf, strlen(sendbuf), 0);
if (strcmp(recvbuf, "1") == 0)
{
sprintf(sendbuf, "You typed ONE\n");
//printf("Sent '%s'\n", sendbuf);
bytesSent = send( AcceptSocket, sendbuf, strlen(sendbuf), 0);
if (bytesSent == SOCKET_ERROR)
{
printf( "Error at send: %ld\n", WSAGetLastError());
goto fin;
}
}
else if (strcmp(recvbuf, "2") == 0)
{
sprintf(sendbuf, "You typed TWO\n");
//printf("Sent '%s'\n", sendbuf);
bytesSent = send( AcceptSocket, sendbuf, strlen(sendbuf), 0);
if (bytesSent == SOCKET_ERROR)
{
printf( "Error at send: %ld\n", WSAGetLastError());
goto fin;
}
}
else if (strcmp(recvbuf, "exit") == 0)
{
printf( "Client has logged out\n", WSAGetLastError());
goto fin;
}
else
{
// sprintf(sendbuf, "unknown command\n");
//printf("Sent '%s'\n", sendbuf);
// bytesSent = send( AcceptSocket, sendbuf, strlen(sendbuf), 0);
if (bytesSent == SOCKET_ERROR)
{
// printf( "Error at send: %ld\n", WSAGetLastError());
goto fin;
}
}
}
fin:
printf("Client processed\n");
closesocket(AcceptSocket);
return 0;
}
int main(int argc , char *argv[])
{
std::cout << ("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
std::cout << ("Failed. Error Code : %d",WSAGetLastError());
return 1;
}
printf("Initialised.\n");
//Create a socket
if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
{
std::cout << ("Could not create socket : %d" , WSAGetLastError());
}
std::cout << ("Socket created.\n");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 3490 );
//Bind
if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR)
{
std::cout << ("Bind failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
puts("Bind done");
//Listen to incoming connections
listen(s , 3);
//Accept and incoming connection
std::cout << ("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
while(true){
while((new_socket = accept(s , (struct sockaddr *)&client, &c)) != INVALID_SOCKET) {
// Create a new thread for the accepted client (also pass the accepted client socket).
printf( "Client Connected.\n");
DWORD dwThreadId;
CreateThread (NULL, 0, ProcessClient, (LPVOID) new_socket, 0, &dwThreadId);
}
}
if (new_socket == INVALID_SOCKET)
{
std::cout << ("accept failed with error code : %d" , WSAGetLastError());
return 1;
}
closesocket(s);
WSACleanup();
return 0;
}
客户端
/*client*/
#define WIN32_LEAN_AND_MEAN
#pragma comment(lib,"ws2_32.lib")
#include <iostream>
#include <process.h>
#include <string>
#include <winsock2.h>
SOCKET Socket;
#define SERVER "localhost"
int PORT = 3490;
std::string line;
bool chat = false;
class Buffer
{
public:
int ID;
char Message[256];
}sbuffer;
int ClientThread()
{
char buffer[2000]= "";
for(;; Sleep(10))
{
if(recv(Socket, buffer, sizeof(sbuffer), NULL)!=SOCKET_ERROR)
{
strncpy(sbuffer.Message, buffer, sizeof(sbuffer.Message));
std::cout << "<Client:" << sbuffer.ID << ":> " << sbuffer.Message <<std::endl;
ZeroMemory (buffer, sizeof(buffer));
}
}
return 0;
}
int main(void)
{
WSADATA WsaDat;
if(WSAStartup(MAKEWORD(2,2),&WsaDat)!=0)
{
std::cout<<"Winsock error - Winsock initialization failed\r\n";
WSACleanup();
system("PAUSE");
return 0;
}
// Create our socket
Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(Socket==INVALID_SOCKET)
{
std::cout<<"Winsock error - Socket creation Failed!\r\n";
WSACleanup();
system("PAUSE");
return 0;
}
// Resolve IP address for hostname
struct hostent *host;
if((host=gethostbyname(SERVER))==NULL)
{
std::cout<<"Failed to resolve hostname.\r\n";
WSACleanup();
system("PAUSE");
return 0;
}
// Setup our socket address structure
SOCKADDR_IN SockAddr;
SockAddr.sin_port=htons(PORT);
SockAddr.sin_family=AF_INET;
SockAddr.sin_addr.s_addr=*((unsigned long*)host->h_addr);
// Attempt to connect to server
if(connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr))!=0)
{
std::cout<<"Failed to establish connection with server\r\n";
WSACleanup();
system("PAUSE");
return 0;
}
// If iMode!=0, non-blocking mode is enabled.
u_long iMode=1;
ioctlsocket(Socket,FIONBIO,&iMode);
// Main loop
for(;;)
{
// Display message from server
char buffer[1000];
memset(buffer,0,999);
int inDataLength=recv(Socket,buffer,1000,0);
std::cout<<buffer;
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE) ClientThread, NULL, NULL, NULL);
for(;; Sleep(10))
{
std::string buffer;
std::getline(std::cin, buffer);
if (send(Socket, buffer.c_str(), buffer.length(), NULL) < 1){
}
}
int nError=WSAGetLastError();
if(nError!=WSAEWOULDBLOCK&&nError!=0)
{
std::cout<<"Winsock error code: "<<nError<<"\r\n";
std::cout<<"Server disconnected!\r\n";
// Shutdown our socket
shutdown(Socket,SD_SEND);
// Close our socket entirely
closesocket(Socket);
break;
}
Sleep(1000);
}
WSACleanup();
system("PAUSE");
return 0;
}
请帮我解决,我是socket的新手。告诉我该怎么做,因为我会更好地理解代码,它对将来可能需要它的其他人也很有用。
答案 0 :(得分:1)
如果您需要服务器与多个客户端通信,那么您需要某种所有连接客户端的集合。然后,很容易发送到所有连接,或发送到所有连接,但发送连接。
如何在C和C ++之间区别 ,但对于C ++,请查看结构和std::vector
。
在伪代码中,它将是这样的:
while (run_server)
{
poll_all_connections();
if (have_new_connection())
{
accept_new_connection();
add_connection_in_collection();
}
else
{
for (connection in all_connections())
{
if (have_input(connection))
{
input = read_from_connection(connection);
for (send_to in all_connections())
write_to_connection(connection, input)
}
}
}
}
如果您实现上述伪代码,则任何连接的输入都将发送到所有连接。
如果连接断开(错误或断开连接,请不要忘记从集合中删除连接。)
答案 1 :(得分:1)
您必须维护所有客户端套接字连接的列表,然后逐个将数据发送到每个客户端。
或者你可以使用线程来实现如下: -
Server-thread()
{
while(true)
{
/// Accept Connection in ClientSocket.
HandleClient-Thread(ClientSocket) ; // launch a thread for each client .
}
}
HandleClient-Thread(ClientSocket)
{
// handle this client here
}