用c编程向所有客户发送消息

时间:2016-12-12 16:03:04

标签: c sockets tcp-ip

我正在尝试制作聊天程序。服务器将获得一个消息,然后发送所有其他客户端。

从客户端获取消息没有问题。但是当它出现时 SendToAll 功能无效。

感谢您的帮助

服务器

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <errno.h>
    #include <unistd.h>
    #include <arpa/inet.h>


    #define PORT 7777
    #define SIZE 1024


  struct clients{
     struct sockaddr_in clientAddr;
     struct clients *next;
 };




 struct clients *AddClient(struct sockaddr_in new_ClientAddr,struct clients *head)
 {

     struct clients *temp = head;
     puts("burda2");
     int a = 1;
     if(head == NULL)
     {
         temp = (struct clients *)malloc(sizeof(struct clients));
         temp->clientAddr = new_ClientAddr;
         temp->next = NULL;
     }
     else
     {
         while(temp != NULL)
         {
         if(temp->clientAddr.sin_addr.s_addr == new_ClientAddr.sin_addr.s_addr)
         {
        a = 0;
        break;
        }   
             temp = temp->next;
         }
         if(a == 1)
         {
             temp->next = (struct clients *)malloc(sizeof(struct clients));
            temp->next->clientAddr = new_ClientAddr;
            temp = temp->next;
            temp->next = NULL;
         }
         else{
             puts("Its already save");
         }
     }
     return head;
 }
   // --- End of Function AddClient() ---

void SendToAll(char msg[1023], struct sockaddr_in repliedClient, struct clients *head)
 {   
    struct clients *temp = head;
    int clients_socket;
    int byte;
    clients_socket  = socket(AF_INET, SOCK_STREAM, 0);
        if(clients_socket == -1)
            perror("Error On Socket(SendToAll)");
    while(temp != NULL)
    {

       if(repliedClient.sin_addr.s_addr != temp->clientAddr.sin_addr.s_addr)//Dont send msg who to replied
        {
            if(connect(clients_socket, (struct sockaddr *)&temp->clientAddr,
                                                sizeof(struct sockaddr)) == -1)
            {
                perror("Error on Connect(SendToAll)");


            byte = send(clients_socket, msg, strlen(msg), 0);
            printf("%s message send",msg);

            if(byte == -1)
                perror("Error on Send(SendToAll");
            else if(byte == 0)
                printf("Connection've been closed");

            temp = temp->next;
            }
        }
    }

 } 
 // --- End of Function SendToAll() ---



int main(int argc, char *argv[])
{
    struct clients *head = NULL;
    int socket_fd, temp_fd;
    struct sockaddr_in serverAddr,new_clientAddr;
    int structSize,byte;
    char text[1023];

    // Creating socket
    socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    if(socket_fd == -1)
        perror("Error on Soket");

    // Editting Server socket
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(PORT);
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    memset(&(serverAddr.sin_zero), '\0', 8);

    // Bind
    if(bind(socket_fd, (struct sockaddr *)&serverAddr, sizeof(struct sockaddr)) == -1)
        perror("Error on Bind");

   // Start listen the port
   if(listen(socket_fd, 20) == -1  )
        perror("Error on Listen");

    structSize = sizeof(new_clientAddr);

    while(1)
    {
        puts(" ");
        // Accept
        temp_fd = accept(socket_fd , (struct sockaddr *)&new_clientAddr, &structSize);
        if(temp_fd == -1)
            perror("Error on Accept");
        // Recv
        byte = recv(temp_fd, &text, SIZE-1, 0);
        if(byte == -1)
            perror("Error on Recv");
        else if(byte == 0)
            printf("Connection is close\n");
        printf("%s", text);
        //Add to list 
        head = AddClient(new_clientAddr, head);
        //Send message to other clients
        SendToAll(text, new_clientAddr, head);

        close(temp_fd);    
    }


    close(socket_fd);


    return (EXIT_SUCCESS);
}

客户端

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h>

//#define ServerIP "35.162.226.229"
#define ServerIP "127.0.0.1"
#define ServerPort 7777
#define SIZE 1024





int main(int argc, char** argv) {

    int socket_fd;
    struct sockaddr_in serverAddr;
    char text[SIZE],msg[SIZE-20], name[20]text temizlendi,get_msg[1024];
    int byte;
    // Nick
    printf("Please enter your nick"); 
    scanf("%s",name);
    //Create Socket
    socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    if(socket_fd == -1)
        perror("Error on Socket");

    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(ServerPort);
    serverAddr.sin_addr.s_addr =inet_addr(ServerIP);
    memset(&(serverAddr.sin_zero), '\0', 8);

    // Connect to server
    if(connect(socket_fd, (struct sockaddr *)&serverAddr, sizeof(struct sockaddr)) == -1)
        perror("Error on Connect");
    puts("Connected");
    while(1)
    {
        //Get message
        printf(">>>"); scanf("%s",msg);
        //Edit message
        strcpy(text, name);
        strcat(text, " : ");
        strcat(text, msg);
        //Send message
        byte = send(socket_fd, text, strlen(text), 0);
        if(byte == -1)
            perror("Error on Send");
        else if(byte == 0)
            printf("Connection've been closed");
        //Get reply to other users

        recv(socket_fd, &get_msg, SIZE-1, 0);
        printf("Getting message %s", get_msg);
    }
    //Close socket
    close(socket_fd);



    return (EXIT_SUCCESS);
}

1 个答案:

答案 0 :(得分:2)

当您打开SOCK_STREAM连接时,它是双向的,并且一直打开(除非您终止它或超时或类似的东西)。

如果要向所有连接的客户端发送消息,请创建一个循环遍历全局客户端结构的循环。 struct clients{ struct sockaddr_in clientAddr; struct clients *next; }; 并对每个客户端ID执行send()操作。

如果connect()在另一端成功(如果从服务器执行,那么在客户端执行)必须有一个套接字侦听器。即由listen()完成。

总之,你不能从服务器端做到这一点。 而且,要创建一个聊天服务器,您的服务器代码需要执行一些称为I / O多路复用的操作。您编写的代码不会这样做,即您正在使用阻止呼叫的accept()

服务器将执行两项主要任务

  1. 接受连接并跟踪连接
  2. 从已连接的客户端接收消息并将其广播给所有其他客户端。
  3. 这两个操作应该互不阻塞。因此,您还需要线程/多个进程来并行运行这些任务。

    希望它有所帮助。