c - 将数据发送到我的服务器中选定的客户端

标签 c linux sockets

我正在学习套接字编程,我希望客户端何时连接到我的服务器。我可以通过他们的具体地址向他们发送数据..

例如

服务器--->客户端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);

}

客户端可以连接到我,但我不知道当两个客户端都连接时要发送数据...当只有 1 个客户端连接到我的服务器时我可以发送数据,但我如何将数据发送到另一个客户端当我的 2 个客户端同时连接时?

谢谢

最佳答案

首先 - 我想说它写得不好。但既然您正在学习,您就需要了解哪段代码在做什么。

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 实际上会返回客户端信息,例如端口和 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];

后者检索套接字以从中写入

关于c - 将数据发送到我的服务器中选定的客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13023829/

相关文章:

linux - 如何解决基于 ARM 的处理器中的 EGLUT 错误?

java - 套接字编程 java - 套接字连接存活了多长时间?我该如何控制它?

java - 在导出远程对象时,如何强制 RMIIO 库使用我的自定义 RMI 套接字工厂?

c - 在 C 中动态创建一个 TYPE 数组

c - C 中的总线错误 10

c - 如何将 `int` 数组转换为 C 中的 IP 地址字符串?

regex - Grep 模式匹配-下划线

c - 使用 Ptrace 跟踪正在打开的文件的位置

Java 客户端和服务器 - 多个请求

c - 搜索并打印目录的所有文件和子文件夹