首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >简单TCP-服务器

简单TCP-服务器
EN

Stack Overflow用户
提问于 2013-02-16 22:49:10
回答 3查看 1.5K关注 0票数 2

这是一个用于教学目的的基本TCP实现。是否有任何错误或改进需要做。欢迎任何建议!

我只怀疑:

代码语言:javascript
复制
signal(SIGCHLD, SIG_IGN);

这个呼叫是用来防止生动活泼的过程吗?

代码语言:javascript
复制
 #include <netinet/in.h>
 #include <sys/socket.h>
 #include <netdb.h>

 #include <sys/signal.h>

 #include <unistd.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>

 #define BACKLOG 5
 #define MAXSIZE 1024 //max-bytes for read-buffer

void main(){

int sock_ds, ret, length;
int acc_ds; //Accept socket descriptor

struct sockaddr_in addr; //this addres
struct sockaddr rem_addr; //remote address (generic)

char buff[MAXSIZE];

sock_ds = socket(AF_INET, SOCK_STREAM, 0); // => TCP

bzero((char *)&addr, sizeof(addr)); //reset struct
addr.sin_family = AF_INET;
addr.sin_port = htons(25000);
addr.sin_addr.s_addr = INADDR_ANY;
ret = bind(sock_ds, &addr, sizeof(addr));
if(ret == -1){
    perror("Binding error");
    exit(1);
}

ret = listen(sock_ds, BACKLOG); // backlog queue
    if(ret == -1){
    perror("Listen error");
    exit(1);
}

length = sizeof(rem_addr);
signal(SIGCHLD, SIG_IGN); //zombie children management

/*Busy-waiting (server) and concurrency */
while(1){

    /*Repeat until success*/
    while(acc_ds = accept(sock_ds, &rem_addr, &length) == -1){

        if(fork() == 0){ //child-process

            close(sock_ds); //unused from child
            do{
                read(acc_ds, buff, MAXSIZE);
                printf("Message from remote host:&s\n", buff);

            }while(strcmp(buff, "quit") == 0);
            /*Transimission completed: server response  */
            write(acc_ds, "Reading Done", 10);
            close(acc_ds); //socket closed
            exit(0); //exiting from child
        }
        else{
            close(acc_ds); //unused from parent
        }
    }
}

}

EN

回答 3

Stack Overflow用户

发布于 2013-02-16 23:01:00

  1. 返回类型的main不是int。应该是这样的。返回EXIT_SUCCESSEXIT_FAILURE
  2. 不检查socket()调用的结果。应该是这样,否则bind会失败,但是perror()会告诉“无效参数”而不是实际的错误。
  3. 不检查read()的返回值,可能会在打印时触发未定义的行为。
  4. 没有指定&s格式,应该是%s格式。
  5. %s需要一个以空结尾的字符串。这不是代码所保证的(参见第3点)。strcmp()也可能会大出血。

至于SIGCHLD,@cnicutar已经善意地回答了这个问题,没有什么可补充的。

希望能帮上忙。祝好运!

票数 3
EN

Stack Overflow用户

发布于 2013-02-16 22:52:27

是的,这正是忽略SIGCHLD的目的。来自TLPI:

还有一种处理死子过程的可能性。显式地将SIGCHLD的配置设置为SIG_IGN将导致随后终止的任何子进程立即从系统中删除,而不是转换为僵尸

它是Unix实现的标准。

票数 2
EN

Stack Overflow用户

发布于 2013-10-12 03:34:51

我也需要知道这是怎么回事。所以,我在googled上搜索了“简单的tcp-server",找到了这个小程序,并用gcc的-Wall和评论修复了代码。以下是我整理的内容:

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

#include <signal.h>

#include <netinet/in.h>
#include <sys/socket.h>
#include <netdb.h>

#include <sys/wait.h>
#include <sys/types.h>
#include <sys/ptrace.h>


#define BACKLOG 5
#define MAXSIZE 1024 //max-bytes for read-buffer

#define PORT 25000

/****************************************************************/
int main() {

  int sock_ds, ret; unsigned int length;
  int acc_ds; //Accept socket descriptor

  struct sockaddr_in addr; //this address
  struct sockaddr rem_addr; //remote address (generic)

  char buff[MAXSIZE+1];

  if (!(sock_ds = socket(AF_INET, SOCK_STREAM, 0))) perror("socket call failed"); // => TCP

  bzero( (char *)&addr, sizeof(addr)); //reset struct
  addr.sin_family = AF_INET;
  addr.sin_port = htons(PORT);
  addr.sin_addr.s_addr = INADDR_ANY;
  ret = bind(sock_ds, (struct sockaddr *)&addr, sizeof(addr));
  if (ret == -1) {
    perror("Binding error");
    exit(EXIT_FAILURE);
  }

  ret = listen(sock_ds, BACKLOG); // backlog queue
  if (ret == (-1)) {
    perror("Listen error");
    exit(EXIT_FAILURE);
  }

  length = sizeof (rem_addr);
  //  sigaction(SIGCHLD, SA_NOCLDWAIT); //zombie children management

  /*Busy-waiting  (server) and concurrency */
  while (1) {
    fprintf(stderr, "[Waiting for client %d]\n", getpid());

    /*Repeat until success*/
    while ((acc_ds = accept(sock_ds, &rem_addr, &length)) == -1) {
      fprintf(stderr, "[Accepted from client %d]\n", getpid());

      if (fork() == 0) { //child-process
        close(sock_ds); //unused from child
        fprintf(stderr, "[Reading from client %d]\n", getpid());
        while (read(acc_ds, buff, MAXSIZE)) {
          buff[MAXSIZE]='\0';
          printf("Message from remote host:%s\n", buff);
          fflush(stdout);
          if (strncmp (buff, "quit", 5) == 0) break;
        }

        /*Transmission completed: server response  */

        if (write(acc_ds, "Reading Done", 10)) fprintf(stderr, "failed write\n");
        close(acc_ds); //socket closed
        exit(EXIT_SUCCESS); //exiting from child
      }
      else{
        close(acc_ds); //unused from parent
      }
    }
  }
  return EXIT_SUCCESS;
}

两个问题。首先,gnu linux gcc拒绝接受。

代码语言:javascript
复制
sigaction(SIGCHLD, SA_NOCLDWAIT); //zombie children management

tcp-server2.c:在函数‘main’:tcp-server2.c:53:3:警告:传递‘σsigaction’的参数2使指针来自整数,而默认情况下不启用tcp所包含的文件中的强制转换-server2.c:7:0: /usr/include/signal.h:267:12:注意:预期的‘构造结构σ动作*限制’,但是参数是‘int’tcp-server2.c:53:3:错误:在文件中包含的函数‘sigaction’的参数太少。tcp-server2.c:7:0: /usr/include/signal.h:267:12:注意:此处声明

第二种情况是,当我打电话到端口25000并键入一些东西时,没有任何东西能像收到的那样得到响应。因此,服务器似乎无法工作。从来没有得到客户的认可。

现在,我可以从其他地方获得一个编程示例,但我认为我应该在这里报告这一点,所以我们在这里发布了一个最简单的tcp服务器。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14915988

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档