一个简单点的阻塞式tcp服务器如下所示:
#include <stdio.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> int main(int argc, char**argv) { int listenfd,connfd,n, ret; struct sockaddr_in servaddr, cliaddr; socklen_t clilen; pid_t childpid; char mesg[1000], *peeraddr; listenfd = socket(AF_INET, SOCK_STREAM, 0); if (listenfd < 0) { printf("create socket error "); return -1; } printf("create socket success "); memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(6789); ret = bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); if (ret == -1) { printf("bind error "); return -1; } printf("bind success "); ret = listen(listenfd, 1024); if (ret == -1) { printf("listen error "); return -1; } printf("listening... "); for (;;) { clilen = sizeof(cliaddr); connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen); printf("Accept request from %s ", inet_ntoa(cliaddr.sin_addr)); n = read(connfd, mesg, 1000); if (n < 0) { printf("read error! "); } printf("Received:%s ", mesg); close(connfd); } }
编译期间没有遇到问题。运行的时候程序在47行收到了segment fault错误。用man手册查看inet_ntoa,调用方式如下:
char *inet_ntoa(struct in_addr in);
cliaddr的类型定义是:
struct sockaddr_in { /* in netinet/in.h */
sa_family_t sin_family; in_port_t sin_port; struct in_addr sin_addr; unsigned char sin_zero[sizeof(struct sockaddr) - sizeof(sa_family_t) - sizeof(in_port_t), sizeof(struct in_addr)]; };
乍一看,没什么问题啊,怎么会出现段错误呢?
捣腾了半天,才发现是缺少了inet_ntoa所在的头文件 arpa/inet.h,包含该头文件即可。好坑。
BTW,以后尽量少使用inet_ntoa,要多用inet_ntop代替它。