[英]Simple TCP-Server
This is a basic TCP-Server implementation for teaching purposes. 这是用于教学目的的基本TCP-Server实现。 Are there any error or improvements to do.
是否有任何错误或改进措施。 Any suggest is welcome!
任何建议都欢迎!
I only have a doubt: 我只有一个疑问:
signal(SIGCHLD, SIG_IGN);
Is that call used to prevent zoombie-child processes? 该呼叫是否用于防止zoombie-child过程?
#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
}
}
}
} }
main
is not int
. main
返回类型不是int
。 It should be. EXIT_SUCCESS
or EXIT_FAILURE
. EXIT_SUCCESS
或EXIT_FAILURE
。 socket()
call is not checked. socket()
调用的结果。 It should be, or bind
will fail but perror()
will tell "Invalid argument" instead of the actual error. bind
将会失败,但perror()
会告诉“无效参数”,而不是实际错误。 read()
is not checked possibly triggering undefined behavior when printing. read()
返回值,有可能在打印时触发未定义的行为。 &s
format specified, it should be %s
. &s
格式,应为%s
。 %s
expects a null-terminated string. %s
需要一个以空值结尾的字符串。 This is not guaranteed by the code (see point #3). strcmp()
may crap out as well. strcmp()
也可能出现故障。 As for the SIGCHLD
, @cnicutar has kindly answered that already, nothing to add there. 至于
SIGCHLD
,@ cnicutar已经很好地回答了,没有什么可补充的。
Hope it helps. 希望能帮助到你。 Good Luck!
祝好运!
Yes, that's exactly what ignoring SIGCHLD is for. 是的,这正是忽略SIGCHLD的目的。 From TLPI:
从TLPI:
There is a further possibility for dealing with dead child processes.
还有处理死掉的子进程的可能性。 Explicitly setting the disposition of SIGCHLD to SIG_IGN causes any child process that subsequently terminates to be immediately removed from the system instead of being converted into a zombie .
将SIGCHLD的处置方式显式设置为SIG_IGN会导致随后终止的所有子进程立即从系统中删除, 而不是转换为僵尸 。
It is standard across Unix implementations. 它是Unix实现中的标准配置。
I need to learn how this works, too. 我也需要学习这是如何工作的。 So, I googled "simple tcp-server", found this little program, and fixed up the code to be happier with gcc -Wall and the comments.
因此,我搜索了“简单的tcp-server”,找到了这个小程序,并使用gcc -Wall和注释将代码固定为更快乐。 here is what I put together:
这是我整理的:
#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;
}
two problems. 两个问题。 the first is that gnu linux gcc refuses to accept
首先是gnu linux gcc拒绝接受
sigaction(SIGCHLD, SA_NOCLDWAIT); //zombie children management
tcp-server2.c: In function 'main': tcp-server2.c:53:3: warning: passing argument 2 of 'sigaction' makes pointer from integer without a cast [enabled by default] In file included from tcp-server2.c:7:0: /usr/include/signal.h:267:12: note: expected 'const struct sigaction * restrict ' but argument is of type 'int' tcp-server2.c:53:3: error: too few arguments to function 'sigaction' In file included from tcp-server2.c:7:0: /usr/include/signal.h:267:12: note: declared here
tcp-server2.c:在函数'main'中:tcp-server2.c:53:3:警告:传递'sigaction'的参数2使指针从整数开始而没有强制转换[默认启用]在tcp-server2包含的文件中.C:7:0:/usr/include/signal.h:267:12:注:应为'const的结构的sigaction * 限制 ',但参数的类型的'INT' TCP-server2.c:53:3:错误: tcp-server2.c:7:0:/usr/include/signal.h:267:12包含的文件中的参数'sigaction'的参数太少:注意:在这里声明
the second is that when I telnet to port 25000 and type a few things, nothing ever is echoed as received. 第二个是,当我远程登录到端口25000并键入一些内容时,接收到的内容不会回显。 so the server does not seem to work.
因此服务器似乎无法正常工作。 it never gets to accepted from client.
它永远不会被客户接受。
now, I could pick up a programming example from somewhere else, but I thought I should just report this here, so we get a simplest tcp server posted correct here. 现在,我可以从其他地方获取一个编程示例,但是我认为我应该只在此处报告此内容,因此我们在这里得到了一个最简单的tcp服务器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.