【发布时间】:2017-09-28 12:16:33
【问题描述】:
当我连接了多个客户端时,我将如何发送给特定的客户端。我想到了sendto(); 但我在同一个套接字上运行所有这些,我不确定为sendto() 存储它们的地址的方法。所以也许我接受多个客户的方式不是很好?
我的服务器代码:
#include "stdafx.h"
#include <stdio.h>
#include <winsock.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
#define _WIN32_WINNIT 0x0500
#include <windows.h>
WSADATA wsa;
SOCKET sock, newsock;
int c;
int clientnum;
struct sockaddr_in server, client;
DWORD WINAPI ProcessClient(LPVOID lpParam) {
SOCKET newSock = (SOCKET)lpParam;
// Send and receive data.
char buf[256];
char newbuf[256];
char cnumchar[5];
strcpy(buf, "Hello Client #: ");
itoa(clientnum, cnumchar, 10);
strcat(buf, cnumchar);
sendto(newSock, buf, sizeof(buf), 0, NULL, NULL);
char sendbuf[256];
strcpy(sendbuf, "a");
while (1)
{
if (recv(newSock, newbuf, sizeof(newbuf), 0) == 0 || recv(newSock, newbuf, sizeof(newbuf), 0) == -1) {
printf("\nClient disconnected");
clientnum--;
}
else if (send(newSock, sendbuf, sizeof(sendbuf), 0) == 0 || send(newSock, sendbuf, sizeof(sendbuf), 0) == -1) {
printf("\nClient Disconnected!");
clientnum--;
}
}
}
int main()
{
printf("Initializing Winsock...\n");
int ret = WSAStartup(MAKEWORD(2, 2), &wsa);
if (ret != 0)
{
printf("Initialization Failed. Error: %d", ret);
return 1;
}
printf("Initialized.\n");
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
printf("Could not create socket! Error: %d\n", WSAGetLastError());
return 1;
}
//textcolor(2);
printf("Socket Created!\n");
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(3939);
//bind
if (bind(sock, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) {
printf("Bind failed! Error: %d\n", WSAGetLastError());
closesocket(sock);
getch();
return 1;
}
printf("Binded!\n");
// listen
if (listen(sock, 1) == SOCKET_ERROR) {
printf("Listen failed! Error: %d\n", WSAGetLastError());
closesocket(sock);
return 1;
}
printf("Now Listening...\n");
do {
newsock = SOCKET_ERROR;
do {
newsock = accept(sock, NULL, NULL);
} while (newsock == SOCKET_ERROR);
printf("Client Connected!");
DWORD dwThreadId;
CreateThread(NULL, 0, ProcessClient, (LPVOID)newsock, 0, &dwThreadId);
clientnum++;
} while (true);
返回 0; }
【问题讨论】:
-
您有一个 listening 套接字,但每个连接的客户端都有自己的 connection 套接字(这是
accept()返回的内容)。要发送到特定客户端,只需使用正确的套接字(为该客户端返回的accept())。但是,您确实只有一个clientnum的全局副本,这可能会导致混淆(当线程读取它时,它的值可能与创建线程时的值不同)。 -
好的,我会考虑使用不同的连接套接字,谢谢!并且 clientnum 事情按预期工作,并向每个客户显示其相应的客户编号。我唯一的另一个问题是检测客户端断开连接和客户端编号——;根本不起作用。
-
在我看来,您在主线程中侦听并在不同线程中处理客户端方面走在了正确的轨道上。您还将正确的套接字传递给线程以处理客户端。如果您想将数据从一个客户端发送到另一个客户端,您可能只需要所有已连接客户端的全局列表?
-
“ProcessClient()”中的“recv()”没有问题吗..???您在“if”语句中可能执行了两个recv(假设第一个recv()不返回零)......这意味着您将丢失您在第一个“recv()”中读取的任何内容。你应该做一个recv(),保存它的返回码,然后用“if”语句测试它。
-
真正的托尼我今天会改变它并检查我保存到的任何东西的返回。是的,卢卡斯。我希望能够知道哪个客户端是哪个客户端,如果我输入 1,它会在服务器程序中仅向客户端 1 发送特定消息。