我正在学习套接字编程,我希望当客户端连接到我的服务器时。我可以用他们的具体地址向他们发送数据..
e.g
服务器--->客户1
╚--->客户2
╚--->客户3
连接自:192.168.5.3
连接自:192.168.5.10
连接自:192.168.5.15
例如说客户端1向我发送数据然后客户端2也向我发送数据我想回复给客户端1我怎么可能这样做?...
我将如何存储我的客户端,以便当我需要向他们发送数据时,我知道我将向哪个客户端发送数据?
这是我的代码。
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>
#include <sys/select.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <poll.h>
#define TRUE 1
#define FALSE 0
typedef struct SERVER_FD{
int sPort;
int serverFD;
int smaxFD;
int newFD;
}sSD;
pid_t pid, sid;
int cFD,
dSize,
err,
start = 1,
state,
DescRead,
DCSERVER = FALSE;
int fd;
char buf[255];
int nbytes;
struct sockaddr_in addr, cli_addr;
unsigned long ip;
char strbuf[256];
socklen_t clilen;
fd_set fdin, fduse;
struct pollfd pfds[2];
int rc;
void process(int ServerFD, int Port, int sMax, int NewSFD);
void cleanUP(int i, int max);
void dlogs(unsigned long ip);
main (int argc, char *argv[])
{
sSD link;
sSD *sCon;
sCon = &link;
sCon->sPort = 53234;
fd = open("/tmp/myFIFO", O_RDWR);
if(fd == -1) {
printf("Could not open the pipe\n");
}
fcntl(fd, F_SETFL,
fcntl(fd, F_GETFL) |
O_NONBLOCK);
sCon->serverFD = socket(AF_INET, SOCK_STREAM, 0);
if (sCon->serverFD != -1)
{
err = setsockopt(sCon->serverFD, SOL_SOCKET, SO_REUSEADDR,(char *)&start, sizeof(start));
if (err != -1)
{
err = ioctl(sCon->serverFD, FIONBIO, (char *)&start);
if (err != -1){
process(sCon->serverFD,sCon->sPort,sCon->smaxFD,sCon->newFD);
}
else{
perror("ioctl() failed");
close(sCon->serverFD);
exit(EXIT_FAILURE);
}
}
else{
perror("setsockopt() failed");
close(sCon->serverFD);
exit(EXIT_FAILURE);
}
}
else{
perror("FAILED CONNECTING TO SOCKET");
exit(EXIT_FAILURE);
}
}
void process(int ServerFD, int Port, int sMax, int NewSFD){
bzero((char *) &addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = 0;
addr.sin_port = htons(Port);
err = bind(ServerFD,(struct sockaddr *)&addr, sizeof(addr));
if (err < 0)
{
perror("bind() failed");
close(ServerFD);
exit(EXIT_FAILURE);
}
err = listen(ServerFD, 32);
if (err < 0)
{
perror("listen() failed");
close(ServerFD);
exit(EXIT_FAILURE);
}
clilen = sizeof(cli_addr);
FD_ZERO(&fdin);
sMax = ServerFD;
FD_SET(ServerFD, &fdin);
do
{
fduse = fdin;
//printf("Waiting on select()...\n");
err = select(sMax + 1, &fduse, NULL, NULL, NULL);
if (err < 0)
{
perror(" select() failed");
break;
}
DescRead = err;
for (cFD=0; cFD <= sMax && DescRead > 0; ++cFD)
{
if (FD_ISSET(cFD, &fduse))
{
DescRead -= 1;
if (cFD == ServerFD)
{
//printf(" Listening socket is readable\n");
do
{
NewSFD = accept(ServerFD,(struct sockaddr *) &cli_addr, &clilen);
if (NewSFD < 0)
{
if (errno != EWOULDBLOCK)
{
perror(" accept() failed");
DCSERVER = TRUE;
}
break;
}
ip = ntohl(cli_addr.sin_addr.s_addr);
printf(" Connection from %d.%d.%d.%d\n",
(int)(ip>>24)&0xff,
(int)(ip>>16)&0xff,
(int)(ip>>8)&0xff,
(int)(ip>>0)&0xff);
dlogs(ip);
FD_SET(NewSFD, &fdin);
if (NewSFD > sMax)
sMax = NewSFD;
} while (NewSFD != -1);
}
else
{
//printf(" Descriptor %d is readable\n", cFD);
pfds[0].fd = fd;
pfds[0].events = POLLIN;
pfds[1].fd = cFD;
pfds[1].events = POLLIN;
state = FALSE;
do
{
rc = poll(pfds, 2, -1);
if (pfds[0].revents & POLLIN)
{
while ((nbytes = read(fd, buf, sizeof(buf)-1)) > 0)
{
buf[nbytes] = '\0';
printf("%s\n", buf);
}
pfds[0].events = 0;
pfds[1].events = POLLIN | POLLOUT;
}
if (pfds[1].revents & POLLIN)
{
err = recv(cFD, strbuf, sizeof(strbuf), 0);
if (err < 0)
{
if (errno != EWOULDBLOCK)
{
perror(" recv() failed");
state = TRUE;
}
break;
}
if (err == 0)
{
printf(" Connection closed\n");
state = TRUE;
break;
}
dSize = err;
printf(" %d bytes received\n", dSize);
}
if (pfds[1].revents & POLLOUT)
{
err = send(cFD, buf, strlen(buf), 0);
if (err < 0)
{
perror(" send() failed");
state = TRUE;
break;
}
pfds[0].events = POLLIN;
pfds[1].events = POLLIN;
}
} while (TRUE);
fopen("/sockF.txt","w");
if (state)
{
close(cFD);
FD_CLR(cFD, &fdin);
if (cFD == sMax)
{
while (FD_ISSET(sMax, &fdin) == FALSE)
sMax -= 1;
}
}
}
}
}
} while (DCSERVER == FALSE);
cleanUP(cFD, sMax);
}
void cleanUP(int i, int max){
for (i=0; i <= max; ++i)
{
if (FD_ISSET(i, &fdin))
close(i);
}
}
void dlogs(unsigned long ip){
FILE* pFile = fopen("/sockF.txt", "w+");
fprintf(pFile,"Connection from: %d.%d.%d.%d",
(int)(ip>>24)&0xff,
(int)(ip>>16)&0xff,
(int)(ip>>8)&0xff,
(int)(ip>>0)&0xff);
fclose(pFile);
}
客户端可以连接到我但我不知道当两者连接时它们中的哪一个发送数据...当只有一个客户端连接到我的服务器时我可以发送数据但是我如何将数据发送到另一个当我的客户端2同时连接时客户端?
谢谢,
答案 0 :(得分:0)
首先 - 我会说它写得不好。但是,既然你正在学习,你需要了解哪一段代码正在做什么。
NewSFD = accept(ServerFD,(struct sockaddr *) &cli_addr, &clilen);
NewSFD是仅向客户端发送消息的新连接描述符/套接字。如果你对这个描述符/套接字进行写/发,它将被发送客户端接收。
char * response = "Connection echoed";
send(NewSFD, response, strlen(response), 0); // call returns number of bytes written.
如果您希望在某些时候执行此操作,则需要将此套接字保存在某个结构中并访问它以写入特定客户端。
cli_addr实际上会返回客户端信息,例如port和ip,后者可用于创建新的套接字。但是,您正在使用tcp,它需要通过连接和接受呼叫进行握手。因此,使用保存的连接套接字是合适的选择。
你可以使用像这样的结构
typedef struct _client_fds{
int connected_sock; // copy the returned value of accept sock_addr_in cli_addr;
struct sock_add_in cli_addr // copy the client struct here
} client_fds;
client_fds客户端[MAX];
后者检索要从中写入的套接字