这是一个用于教学目的的基本TCP实现。是否有任何错误或改进需要做。欢迎任何建议!
我只怀疑:
signal(SIGCHLD, SIG_IGN);这个呼叫是用来防止生动活泼的过程吗?
#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
}
}
}}
发布于 2013-02-16 23:01:00
main不是int。应该是这样的。返回EXIT_SUCCESS或EXIT_FAILURE。socket()调用的结果。应该是这样,否则bind会失败,但是perror()会告诉“无效参数”而不是实际的错误。read()的返回值,可能会在打印时触发未定义的行为。&s格式,应该是%s格式。%s需要一个以空结尾的字符串。这不是代码所保证的(参见第3点)。strcmp()也可能会大出血。至于SIGCHLD,@cnicutar已经善意地回答了这个问题,没有什么可补充的。
希望能帮上忙。祝好运!
发布于 2013-02-16 22:52:27
是的,这正是忽略SIGCHLD的目的。来自TLPI:
还有一种处理死子过程的可能性。显式地将SIGCHLD的配置设置为SIG_IGN将导致随后终止的任何子进程立即从系统中删除,而不是转换为僵尸。
它是Unix实现的标准。
发布于 2013-10-12 03:34:51
我也需要知道这是怎么回事。所以,我在googled上搜索了“简单的tcp-server",找到了这个小程序,并用gcc的-Wall和评论修复了代码。以下是我整理的内容:
#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拒绝接受。
sigaction(SIGCHLD, SA_NOCLDWAIT); //zombie children managementtcp-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服务器。
https://stackoverflow.com/questions/14915988
复制相似问题