使用fork和sockets的服务器客户端聊天

使用fork和sockets的服务器客户端聊天,sockets,client,fork,chat,server,Sockets,Client,Fork,Chat,Server,我想创建一个聊天室,服务器可以接受任何客户端,当一个客户端发送一些文本时,服务器会将该消息发送给当时连接的所有其他客户端。到目前为止,我的服务器能够接受许多客户端(通过套接字连接),它们可以发送服务器显示的消息。我的服务器有一个结构,用于随时知道连接了谁(名称和PID)。我的问题是:如何使我的服务器将从一个客户端收到的消息重定向到所有其他客户端 服务器c: #include <stdio.h> #include <stdlib.h> #include <string

我想创建一个聊天室,服务器可以接受任何客户端,当一个客户端发送一些文本时,服务器会将该消息发送给当时连接的所有其他客户端。到目前为止,我的服务器能够接受许多客户端(通过套接字连接),它们可以发送服务器显示的消息。我的服务器有一个结构,用于随时知道连接了谁(名称和PID)。我的问题是:如何使我的服务器将从一个客户端收到的消息重定向到所有其他客户端

服务器c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/mman.h>

typedef struct tabela
{
  char name[50];
  int PID;
} tab;

static tab *tabelaPersoane;

static int *nrPersoaneConectate;

void afisareConectati()
{
  int i;
  if (*nrPersoaneConectate > 0)
  {
    printf("Numarul de persoane conectate: %d", *nrPersoaneConectate);
    printf("\nPersoane conectate:\n");
    for (i = 0; i < *nrPersoaneConectate; i++)
    {
      printf("%s", tabelaPersoane[i].name);
    }
    printf("\n");
  }
  else
    printf("Niciun client conectat!\n");
}

void doprocessing(int sock, char *numeClient)
{
  //printf("doprocessing id=%d\n",sock);
  int n, i;
  char buffer[256], mesaj[256];
  while (1)
  {
    //printf("%d\n",nrPersoaneConectate);
    bzero(buffer, 256);

    n = read(sock, buffer, 255);
    if (strncmp(buffer, "exit", strlen("exit")) == 0)
    {
      for (i = 0; i < *nrPersoaneConectate; i++)
      {
        if (strcmp(numeClient, tabelaPersoane[i].name) == 0)
          if (i != *nrPersoaneConectate - 1)
          {
            tabelaPersoane[i] = tabelaPersoane[*nrPersoaneConectate - 1];
            //printf("%d\n",nrPersoaneConectate);
          }
      }
      (*nrPersoaneConectate)--;
      printf("S-a deconectat %s", numeClient);
      afisareConectati();
      break;
    }
    if (n < 0)
    {
      perror("ERROR reading from socket");
      exit(1);
    }
    if (strcmp(buffer, "") != 0)
    {
      bzero(mesaj, 256);
      strncpy(mesaj, numeClient, strlen(numeClient) - 1);
      strcat(mesaj, ": ");
      strncat(mesaj, buffer, strlen(buffer));
      printf("%s", mesaj);
    }
    n = write(sock, "I got your message", 18);

    if (n < 0)
    {
      perror("ERROR writing to socket");
      exit(1);
    }
  }
}

int main(int argc, char *argv[])
{
  nrPersoaneConectate = mmap(NULL, sizeof *nrPersoaneConectate,
      PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  tabelaPersoane = (tab *) mmap(0, sizeof(tab), PROT_READ | PROT_WRITE,
      MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  int sockfd, newsockfd, portno, clilen;
  char buffer[256], mesaj[256];
  char buffer_pid[6];
  struct sockaddr_in serv_addr, cli_addr;
  int n, i;
  *nrPersoaneConectate = 0;
  /* First call to socket() function */
  sockfd = socket(AF_INET, SOCK_STREAM, 0);

  if (sockfd < 0)
  {
    perror("ERROR opening socket");
    exit(1);
  }

  /* Initialize socket structure */
  bzero((char *) &serv_addr, sizeof(serv_addr));
  portno = 51100;

  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = INADDR_ANY;
  serv_addr.sin_port = htons(portno);

  /* Now bind the host address using bind() call.*/
  if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
  {
    perror("ERROR on binding");
    exit(1);
  }

  /* Now start listening for the clients, here
   * process will go in sleep mode and will wait
   * for the incoming connection
   */

  if (listen(sockfd, 5) < 0)
  {
    printf("error ...");
    exit(1);
  }
  clilen = sizeof(cli_addr);

  while (1)
  {
    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
    //printf("sockfd%d\n",sockfd);
    //printf("newsockfd%d\n",newsockfd);
    if (newsockfd < 0)
    {
      perror("ERROR on accept");
      exit(1);
    }
    (*nrPersoaneConectate)++;
    /* Create child process */
    int pid = fork();
    if (pid < 0)
    {
      perror("ERROR on fork");
      exit(1);
    }

    if (pid == 0)
    {

      /* This is the client process */
      close(sockfd);
      if (write(newsockfd, "Name: ", sizeof("Name: ")) < 0)
      {
        printf("Error on sending \"Name: \" string.");
        exit(1);
      }
      if (read(newsockfd, buffer, 255) < 0)
      {
        printf("Error on reading the name response.");
        exit(1);
      }
      strcpy(tabelaPersoane[(*nrPersoaneConectate) - 1].name, buffer);
      tabelaPersoane[(*nrPersoaneConectate) - 1].PID = getpid();
      bzero(mesaj, 256);
      strcpy(mesaj, "S-a conectat ");
      strncat(mesaj, buffer, strlen(buffer) - 1);
      strcat(mesaj, " PID: ");
      sprintf(buffer_pid, "%d", tabelaPersoane[(*nrPersoaneConectate) - 1].PID);
      strcat(mesaj, buffer_pid);
      strcat(mesaj, "\n");
      printf("%s", mesaj);
      afisareConectati();
      doprocessing(newsockfd, buffer);
      exit(0);
    }
    else
    {

      close(newsockfd);
      //printf("Close\n");         
    }
  } /* end of while */
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
typedef结构选项卡
{
字符名[50];
int-PID;
}标签;
静态选项卡*tabelaPersoane;
静态int*nR过碳酸酯;
void afisarecontati()
{
int i;
如果(*nRPERSOANECONETATE>0)
{
printf(“Numarul de persoane conconnectate:%d”,*nrPersoaneConectate);
printf(“\n联系人:\n”);
对于(i=0;i<*nPersoanectate;i++)
{
printf(“%s”,tabelaPersoane[i].名称);
}
printf(“\n”);
}
其他的
printf(“Niciun客户端连接!\n”);
}
无效数据处理(int sock,char*numclient)
{
//printf(“数据处理id=%d\n”,sock);
int n,i;
char缓冲区[256],mesaj[256];
而(1)
{
//printf(“%d\n”,nrpersoanectate);
b0(缓冲器,256);
n=读取(sock,缓冲区,255);
如果(strncmp(缓冲区,“退出”,strlen(“退出”))==0)
{
对于(i=0;i<*nPersoanectate;i++)
{
if(strcmp(numclient,tabelaPersoane[i].name)==0)
如果(i!=*nRPERSOANECONETATE-1)
{
tabelaPersoane[i]=tabelaPersoane[*nPersoanecontate-1];
//printf(“%d\n”,nrpersoanectate);
}
}
(*N-过氯乙酸);
printf(“S-a解除连接到%S”,numeClient);
Afisarecontati();
打破
}
if(n<0)
{
perror(“从套接字读取错误”);
出口(1);
}
如果(strcmp(缓冲区“”)=0)
{
bzero(mesaj,256);
strncpy(mesaj、numeClient、strlen(numeClient)-1;
strcat(mesaj,“:”);
strncat(mesaj,buffer,strlen(buffer));
printf(“%s”,mesaj);
}
n=写(sock,“我收到你的消息”,18);
if(n<0)
{
perror(“写入套接字时出错”);
出口(1);
}
}
}
int main(int argc,char*argv[])
{
nRPersoanectate=mmap(NULL,sizeof*nRPersoanectate,
PROT|u READ | PROT|u WRITE,MAP|u SHARED | MAP|u ANONYMOUS,-1,0);
tabelaPersoane=(tab*)mmap(0,sizeof(tab),PROT_READ | PROT_WRITE,
MAP|u SHARED | MAP|u ANONYMOUS,-1,0);
int sockfd、newsockfd、portno、clilen;
char缓冲区[256],mesaj[256];
字符缓冲区_pid[6];
服务地址中的结构sockaddr\u,cli\u addr;
int n,i;
*nR过氯乙酸乙酯=0;
/*第一次调用socket()函数*/
sockfd=套接字(AF_INET,SOCK_STREAM,0);
if(sockfd<0)
{
perror(“错误打开插座”);
出口(1);
}
/*初始化套接字结构*/
bzero((char*)&serv_addr,sizeof(serv_addr));
端口号=51100;
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=INADDR_ANY;
serv_addr.sin_port=htons(端口号);
/*现在使用bind()调用绑定主机地址*/
if(bind(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))<0)
{
perror(“绑定错误”);
出口(1);
}
/*现在开始收听客户,这里
*进程将进入睡眠模式并等待
*用于传入连接
*/
如果(听(sockfd,5)<0)
{
printf(“错误…”);
出口(1);
}
clilen=sizeof(cli_addr);
而(1)
{
newsockfd=accept(sockfd,(struct sockaddr*)&cli\u addr,&clilen);
//printf(“sockfd%d\n”,sockfd);
//printf(“newsockfd%d\n”,newsockfd);
if(newsockfd<0)
{
perror(“接受错误”);
出口(1);
}
(*nR过氯乙酸乙酯)+;
/*创建子进程*/
int-pid=fork();
if(pid<0)
{
perror(“叉子上的错误”);
出口(1);
}
如果(pid==0)
{
/*这是客户端进程*/
关闭(sockfd);
如果(写入(newsockfd,“Name:”,sizeof(“Name:”)<0)
{
printf(“发送\”名称时出错:\“字符串”);
出口(1);
}
如果(读取(newsockfd,缓冲区,255)<0)
{
printf(“读取名称响应时出错”);
出口(1);
}
strcpy(tabelaPersoane[(*nrpersoanectate)-1]。名称,缓冲区;
tabelaPersoane[(*nrpersoaneconetate)-1].PID=getpid();
bzero(mesaj,256);
strcpy(mesaj,“S-a连接”);
strncat(mesaj,缓冲区,strlen(缓冲区)-1);
strcat(mesaj,“PID:”);
sprintf(buffer_pid,“%d”,tabelaPersoane[(*nrPersoaneConectate)-1].pid);
strcat(mesaj,缓冲器pid);
strcat(mesaj,“\n”);
printf(“%s”,mesaj);
Afisarecontati();
数据处理(newsockfd,缓冲区);
出口(0);
}
其他的
{
关闭(newsockfd);
//printf(“关闭”);
}
}/*结束时*/
}
客户c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
  int sockfd, portno, n;
  struct sockaddr_in serv_addr;
  struct hostent *server;

  char buffer[256];

  if (argc < 3)
  {
    fprintf(stderr, "usage %s hostname port\n", argv[0]);
    exit(0);
  }
  portno = atoi(argv[2]);

  /* Create a socket point */
  sockfd = socket(AF_INET, SOCK_STREAM, 0);

  if (sockfd < 0)
  {
    perror("ERROR opening socket");
    exit(1);
  }
  server = gethostbyname(argv[1]);
  if (server == NULL )
  {
    fprintf(stderr, "ERROR, no such host\n");
    exit(0);
  }
  bzero((char *) &serv_addr, sizeof(serv_addr));
  serv_addr.sin_family = AF_INET;
  bcopy((char *) server->h_addr,
  (char *)&serv_addr.sin_addr.s_addr,
  server->h_length);
  serv_addr.sin_port = htons(portno);

  /* Now connect to the server */
  if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
  {
    perror("ERROR connecting");
    exit(1);
  }
  if (read(sockfd, buffer, 255) < 0)
  {
    printf("Error on reading \"Name: \" string.");
    exit(1);
  }
  printf("%s", buffer);
  bzero(buffer, 256);
  fgets(buffer, 255, stdin);
  fflush(stdin);
  if (write(sockfd, buffer, sizeof(buffer)) < 0)
  {
    printf("Error on sending %s", buffer);
    exit(1);
  }

  /* Now ask for a message from the user, this message
   * will be read by server
   */
  while (1)
  {
    printf("Please enter the message: ");
    bzero(buffer, 256);
    fgets(buffer, 255, stdin);
    //printf("buffer=%s\n",buffer);
    if (strncmp(buffer, "exit", strlen("exit")) == 0)
    {
      //printf("Am iesit din while!\n(Din client)");
      n = write(sockfd, buffer, strlen(buffer));
      if (n < 0)
      {
        perror("ERROR writing to socket");
        exit(1);
      }
      break;
    }

    /* Send message to the server */
    n = write(sockfd, buffer, strlen(buffer));
    if (n < 0)
    {
      perror("ERROR writing to socket");
      exit(1);
    }

    /* Now read server response */
    bzero(buffer, 256);
    n = read(sockfd, buffer, 255);

    if (n < 0)
    {
      perror("ERROR reading from socket");
      exit(1);
    }
    printf("%s\n", buffer);
    //strcpy(buffer,"");
    //fflush(stdin);

  }
  return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int main(int argc,char*argv[])
{
int sockfd,端口号,n;
服务地址中的结构sockaddr\u;
结构主机*服务器;
字符缓冲区[256];
如果(argc<3)
{
fprintf(stderr,“使用%s主机名端口,\n”,argv[0]);
出口(0);
}
portno=atoi(argv[2]);
/*创建一个套接字点*/
sockfd=套接字(AF_INET,SOCK_STREAM,0);
if(sockfd<0)
{
perror(“错误打开插座”);
出口(1);
}
server=gethostbyname(argv[1]);
如果(服务器==NULL)
{
fprintf(stderr,“错误,没有这样的主机\n”);
出口(0);
}
bzero((char*)&serv_addr,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
b复制((字符*)服务器->h_地址,
(char*)和serv_addr.sin_addr.s_addr,
服务器->h_长度);
serv_addr.sin_port=htons(端口号);
/*现在连接到服务器*/
if(connect(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))<0)
{
体育课