它可以基于TCP协议,服务器就在TCP端口七检测有无消息,如果使用UDP协议,基本过程和TCP一样,检测的端口也是七。他也是路由也是网络中最常用的数据纤巧包,可以通过发送echo包知道当前的毁敬键连接节点有那些路径,并且通过往返时间能得出路径长度。
先 netstat -nl | grep 9999 看看是否有进程已经在9999端樱坦辩口侦听,如果有,kill掉那个脊缺进程,或者改用其他端口。然后,用下面修改过的代信蠢码。至于调试,很简单, 用 gdb 调试 server端即可,由于你是用fork子进程来处理新连接,需要在gdb里 set follow-fork-mode child。具体自己去学gdb吧。或者你改成不用fork,单进程处理,比如用 select/pthread 等手段,这样也比较好调试。
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <strings.h>
#include <unistd.h>
#define MAXLINE 4096
void echo_write(int sockfd)
ssize_t written(int sockfd, const void *buf, size_t nbytes)
ssize_t readline(int sockfd, void *buf, int maxlen)
int main(int argc, char **argv) {
int listenfd, connfd, len
pid_t pid
struct sockaddr_in servaddr, cliaddr
char bufaddr[MAXLINE]
listenfd = socket(AF_INET, SOCK_STREAM, 0)
servaddr.sin_family = AF_INET
servaddr.sin_addr.s_addr = htonl(INADDR_ANY)
servaddr.sin_port = htons(9999)
bind(listenfd, (struct sockaddr*) &servaddr, sizeof(servaddr))
listen(listenfd, 100)
for( ) {
len = sizeof(cliaddr)
connfd = accept(listenfd, (struct sockaddr*) &cliaddr, &len)
printf("accept ok\n")
if( (pid = fork()) == 0) {
printf("connection from %s : %d\n",
inet_ntop(AF_INET, &cliaddr.sin_addr, bufaddr, sizeof(bufaddr)),
ntohs(cliaddr.sin_port))
close(listenfd)
printf("echo_write start.\n")
echo_write(connfd)
close(connfd)
exit(0)
}
close(connfd)
}
exit(0)
}
void echo_write(int sockfd) {
char buf[MAXLINE]
ssize_t n
printf("let's read.\n")
again:
printf("begin read.\n")
while( (n = readline(sockfd, buf, MAXLINE)) >0) {
printf("n: %d\n", n)
written(sockfd, buf, n)
printf("written ok.\n")
}
if(n <0 &&errno == EINTR) {
goto again
} else if(n <0) {
printf("read error")
}
}
ssize_t readline(int sockfd, void *buf, int maxlen) {
char *ptr, c
ssize_t n, rc
ptr = buf
for(n = 1n <maxlenn++) {
again:
if( (rc = read(sockfd, &c, 1)) == 1) {
*ptr++ = c
if(c == '\n') {
break
}
} else if(rc == 0) {
*ptr = 0
return n - 1
} else {
if(rc <0 &&errno == EINTR) {
goto again
}
return -1
}
}
*ptr = 0
return n
}
ssize_t written(int sockfd, const void *buf, size_t nbytes) {
const char *buf_ptr
size_t nleft = nbytes
ssize_t nwritten
buf_ptr = buf
while(nleft >0) {
if( (nwritten = write(sockfd, buf_ptr, nleft)) <= 0) {
if(nwritten <0 &&errno == EINTR) {
nwritten = 0
} else {
return -1
}
}
nleft -= nwritten
buf_ptr += nwritten
}
return nbytes
}
反复从标准输入读取文本行,发送文谈宽本行给服务器。从服务器读取回送的行,并输出结果到标准输出。当fgets在标准输入上遇到EOF时,或者因为用户在键盘含纯亮上输入ctrl加D,或者在遇到一个重定向的输入文件中用尽了所有的文本行时,循环截止。
服务器主程序,打开监听描述符,进入循环,等待一个来自客户端的连接请求,输出已连接的客户端域名和IP地址,并调裤耐用echo函数为这个客户端服务。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)