2014-11-02 33 views
3

我正在研究一个简单的项目,因为我想了解更多关于Linux下套接字编程的知识。我创建了一个非常简单的服务器,它将接受连接并用单个语句进行响应。但是,我添加了一个while循环来保持连接的活跃,所以我可以在不断开连接的情况下继续发送命令。但是,一旦我发送第一个命令,服务器就会响应连接。在第一个响应之后,它只是闲置并退出响应。从代码中可以看出,我在while循环内部和外部尝试了accept系统调用,因为我不确定如果调用在同一个客户端上多次接受会导致它挂起。一旦我在while循环之外移动accept函数,函数仍然挂起,所以我不确定从这里开始去哪里。C和Linux中的套接字连接问题

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

struct server { 
    int sockfd; 
    int client_socket; //the socket used for communication with the client 
    int backlog; //maximum pending connections 
    struct sockaddr_in *serv_addr; 
    struct sockaddr_in *client_addr; //the clients information when it connects 
}; 

int server_init(server **serv, int max_connections) 
{ 
    *serv = (server *)malloc(sizeof(server)); 
    if (*serv) { 
     (*serv)->backlog = max_connections; 
     (*serv)->sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 

     (*serv)->serv_addr = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in)); 
     if ((*serv)->serv_addr) 
      memset((*serv)->serv_addr->sin_zero, 0, sizeof((*serv)->serv_addr->sin_zero)); 
     else { 
      free(*serv); 
      return -1; 
     } 

     (*serv)->serv_addr->sin_family = AF_INET; 
     (*serv)->serv_addr->sin_addr.s_addr = INADDR_ANY; 

    } else { 
     return -1; 
    } 

    return 0; 
} 

/* 
* Bind the server to a port and start listening 
*/ 
int server_bind(server *serv, int port) 
{ 
    int result = 0; 

    serv->serv_addr->sin_port = htons(port); 
    if (bind(serv->sockfd, (struct sockaddr *)serv->serv_addr, (socklen_t)sizeof(*(serv->serv_addr))) < 0) 
     return -1; //if the bind call fails, I dont want to continue to try the listen call 

    if (listen(serv->sockfd, serv->backlog) < 0) 
     result = -1; 

    return result; 
} 

int server_unbind(server *serv) 
{ 
    int result = 0; 

    if (close(serv->client_socket) < 0) 
     result = -1; 

    if (close(serv->sockfd) < 0) 
     result = -1; 

    return result; 
} 

int server_accept_connections(server *serv, int (*process_data)(char *buffer, ssize_t length, int client_scoket)) 
{ 
    int result = 0; 
    char *buffer = (char *) malloc(sizeof(char) * 250); 

    if (buffer) { 
     int length = sizeof((serv)->client_addr); //may do something with this to keep from calculating it every time 
     serv->client_socket = accept(serv->sockfd, (struct sockaddr *)(serv)->client_addr, &length); 

     while (result == 0) { 
      //int length = sizeof((serv)->client_addr); 
      //serv->client_socket = accept(serv->sockfd, (struct sockaddr *)(serv)->client_addr, &length); 
      ssize_t data_length = recv(serv->client_socket, buffer, sizeof(buffer), 0); 
      result = (* process_data)(buffer, data_length, serv->client_socket); 
     } 
     result = 0; 
    } 
    else 
     result = -1; 

    free(buffer); 
    return result; 
} 

void server_destroy(server *serv) 
{ 
    if (serv) { 
     free(serv->serv_addr); 
     free(serv); 
    } 
} 

#include <stdio.h> 
#include "server.h" 
#include <string.h> 
#include <stdlib.h> 

int process_netdata(char *buffer, ssize_t length, int socket_desc) 
{ 
    printf("%s",buffer); 
    if(strcmp(buffer, "quit") != 0) { 
     char *str = "I got your message"; 
     int str_length = strlen(str); 
     write(socket_desc, str, str_length); 
     return 0; 
    } 
    else { 
     char *str = "quit received"; 
     int str_length = strlen(str); 
     write(socket_desc, str, str_length); 
     return -1; 
    } 
} 

int main(int argc, char **argv) 
{ 
    server *server; 
    int value = 0; 

    value = server_init(&server, 10); 
    printf("server_init: %i\n", value); 

    value = server_bind(server, 2021); 
    printf("server_bind: %i\n", value); 

    value = server_accept_connections(server, &process_netdata); 
    printf("server_accept: %i\n", value); 

    value = server_unbind(server); 
    printf("server_unbind: %i\n", value); 

    value = server_destroy(server); 
    printf("server_destroy: %i\n", value); 

    return 0; 
} 
+2

最好直接在这里发布代码,而不是将用户重定向到其他网站。以[SSCCE](http://sscce.org/)为例,如果可能的话,编辑你的问题。 – streppel 2014-11-02 01:42:55

+0

或者在SO帮助中看看这里:http://stackoverflow.com/help/mcve – 2014-11-02 02:16:03

回答

2

你缺少到餐桌,使家长继续听(接受)新的连接,而孩子所建立的连接上运行。

+0

感谢您的帮助。 – Christopher 2014-11-02 02:44:09