C - 在服务器和客户端之间创建无限的套接字连接(Linux)

时间:2015-07-08 21:08:49

标签: c sockets ubuntu client server

我有一个用C创建的简单套接字程序(使用Ubuntu),连接正常,服务器编译,客户端提供IP和端口号。

但是建立连接后,客户端只能send one message,然后只能connection closes。当客户端发送消息时,服务器会收到消息并发送程序ends by itself

我尝试使用while loop,但它给了我一个Error on binding。有没有办法让它无限,所以当用户输入exit或某些specific key/command时,程序就会结束。

server.c UPDATED with WHILE LOOP

#include<stdio.h>  
#include<stdlib.h>  
#include<sys/types.h>     
#include<sys/socket.h>  
#include<netinet/in.h>  
#include<string.h>  

int main(int argc, char *argv[])  
{  
      int sockfd, newsockfd, portNum, clien, n;
      char buffer[256];
      struct sockaddr_in serv_addr,cli_addr;
  if (argc < 2)
  {
        fprintf(stderr, "\nno port provided");
        exit(1);
  }

  sockfd = socket(AF_INET,SOCK_STREAM, 0);
  if (sockfd < 0)
        printf("\nprovide a valid port number\n");

  bzero((char *)&serv_addr, sizeof(serv_addr));
  portNum = atoi(argv[1]);

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

  if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0 )
        printf("error on binding");

  while(1)
  {
       listen(sockfd,5);
  }
  clien = sizeof(cli_addr);
  newsockfd=accept(sockfd, (struct sockaddr *) &cli_addr, &clien );

  if (newsockfd < 0)
        printf("=> Error on accepting...\n");

  bzero(buffer, 256);  
  n = read(newsockfd, buffer, 256); 

  if (n < 0)  
        printf("error reading from socket...\n");

  printf("%s\n", buffer);
  n = write(newsockfd, "message received.", 58);

  if (n < 0)
        printf("cannot write from socket...\n");

  return 0;
}

client.c UPDATED with WHILE LOOP

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

int main(int argc, char *argv[])  
{  
      int sockfd,portno,n;
      char buffer[256];
      struct sockaddr_in serv_addr;
      struct hostent *server;

      //while(counter != 5)
      // /{
            if (argc < 3)
      {  
            fprintf(stderr,"Usage %s hostname port...\n",argv[0]);
            exit(1);
      }

      portno = atoi(argv[2]);
      sockfd = socket(AF_INET, SOCK_STREAM, 0);
      if (sockfd < 0)
            printf("\error opening socket...\n");

      bzero((char *) &serv_addr, sizeof(serv_addr));
      server = gethostbyname(argv[1]);

      if (server == NULL)
      {
            fprintf(stderr,"no such host...\n");
            exit(0);
      }

      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);

      if (connect(sockfd, &serv_addr,sizeof(serv_addr)) <0 )  
            printf("\error connecting\n");

      printf("your message:");
      fgets(buffer, 256, stdin);
      while(1)
      {
            n = write(sockfd,buffer,strlen(buffer));
      }
      if (n < 0)
            printf("error writing to socket\n");

      n = read(sockfd, buffer, 255);

      if (n < 0)
            printf("error reading from socket\n");

      printf("%s\n", buffer);          

      return 0;
}

谢谢。

2 个答案:

答案 0 :(得分:2)

您的服务器的问题是您在收到消息时立即终止。你应该做的是继续使用recv()函数进行监听,直到客户端断开连接。这是一段应该做的诀窍。

免责声明:不过我还没有测试过它,它来自我为你修改的旧项目,它应该可以工作但是我不是百分之百确定它,我现在没时间测试它但如果出现问题,请随时提问,我会尽力纠正。

编辑:尝试重新生成导致错误,因为绑定已经完成且端口已经忙,所以你不能“分配”另一个程序到这个端口,因此给你一个错误。您唯一需要做的就是确保服务器监听,直到客户端与服务器断开连接。

此外,有些代码可能是在某些时候为c ++编写的,但网络部分应该可以正常工作。

如果您有任何疑问,请随意尝试并发表评论。 Server.c:

    int socket_desc , client_sock , c , *new_sock;
    struct sockaddr_in server , client;

    socket_desc = socket(AF_INET , SOCK_STREAM , 0);
    if (socket_desc == -1)
    {
        //HANDLE ERROR
    }
    printf("Socket created\n");

    //Prepare the sockaddr_in structure
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons( 8000 );

    //Binding, you already do it correctly.
    if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server))< 0)
    {
        //ERROR
    }
    printf("bind done");

    //Listen
    listen(socket_desc , 3);

    printf("Waiting for incoming connections...");
    c = sizeof(struct sockaddr_in);


    while( (client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) )
    {
        puts("Connection accepted");

        pthread_t sniffer_thread;
        new_sock = (int*) malloc(1);
        *new_sock = client_sock;

        if( pthread_create( &sniffer_thread , NULL ,  connection_handler , (void*) new_sock) < 0)
        {
            //ERROR
        }

        printf("Handler assigned");
    }

    if (client_sock < 0)
    {
        //ERROR
    }

    //return 0;

}

/*
 * This will handle connection for each client you may have and read indefinitely
 * */
void *connection_handler(void *socket_desc)
{
    //Get the socket descriptor
    int sock = *(int*)socket_desc;
    int read_size;
    char *message , client_message[2000];
    string smatrix ;
    int ind ;
    string tok ;
    int i = 0 ;


    //Receive a message from client
    while( (read_size = recv(sock , client_message , 2000 , 0)) > 0 )
    {
        //What you want to do with the client's message
    }

    if(read_size == 0)
    {
        printf("Client disconnected");
        fflush(stdout);
    }
    else if(read_size == -1)
    {
        //ERROR
    }

    //Free the socket pointer
    free(socket_desc);

对于客户端,执行while循环直到某个时间过去或输入给定的字符或值。类似的东西:

while(wantToExit == false){
   char a;
   printf("Please enter a char");
   scanf("%c", &a);
   write(sock , a , 1); //Note use strlen() for strings
}

希望有所帮助

答案 1 :(得分:1)

您实际期望服务器做什么?你打开/读/终止。终止,当然会隐式关闭套接字 - 幸运的是,当你忘记明确关闭时。

你必须经常从套接字读取。不确定你的意思是“它...给我一个关于绑定的错误”;如果你试图重新绑定,那当然是错的。你不会一次又一次地打开文件,只是为了阅读它的数据。

如果您希望在从另一侧关闭套接字之后监听套接字,则只需在外部循环中使用listen

阅读维基百科,了解有关sockets的基础知识并查看链接。