UNP卷一chapter5 tcp client/server

以下知识点来均来自steven先生所著UNP卷一(version3),刚开始学习网络编程,如有不正确之处请大家多多指正。

1、netstat命令在网络编程的用法

记住一下

netstat -tuanlp  查看激活的网络连接,针对tcp、udp协议  tua:tcp、udp、all,n:no domain,p:PID/Progra

netstat -s 各协议信息

netstat -r 查看路由信息

netstat -i 网络接口信息

其它的具体说明参见https://blog.csdn.net/rockzhai/article/details/7657986

2、ps

利用ps -a 查看所有进程号,再利用ps -t pts/6 -o pid,ppid,tty,stat,args,wchan查看伪终端pts/6上的具体信息

找到对应进程号,再利用kill将进程杀掉

扫描二维码关注公众号,回复: 961994 查看本文章

3、sscanf与snprintf函数用法

具体用法参考:https://blog.csdn.net/Qiuoooooo/article/details/52814631

 4、服务器端程序

#include	"unp.h"

//--------------------------------------------------------
//服务器
//--------------------------------------------------------
void sig_chld(int signo) {
	pid_t pid;
	int stat;
	//-1表示第一个要终止的进程,WNOHANG告知waitpid在尚未终止的子进程在运行时不要阴塞
	while ((pid = waitpid(-1, &stat, WNOHANG)) > 0)
		printf("child %d terminate\n", pid);
	return;
}

void
str_echo(int sockfd)
{
	ssize_t		n;
	char		buf[MAXLINE];

again:
	while ((n = read(sockfd, buf, MAXLINE)) > 0)//从套接字中读入数据
		Writen(sockfd, buf, n);//将内容回射给客户

	if (n < 0 && errno == EINTR)
		goto again;
	else if (n < 0)
		err_sys("str_echo: read error");
}

int
main(int argc, char **argv)
{
	int					listenfd, connfd;
	pid_t				childpid;
	socklen_t			clilen;
	struct sockaddr_in	cliaddr, servaddr;
	void				sig_chld(int);

	listenfd = Socket(AF_INET, SOCK_STREAM, 0);

	bzero(&servaddr, sizeof(servaddr));//地址结构清零
	servaddr.sin_family = AF_INET;//指定协议
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//指定地址,INADDR_ANY为0,并转化为网络字节序
	servaddr.sin_port = htons(SERV_PORT);//指定端口号,转化为网络字节序

	Bind(listenfd, (SA *)&servaddr, sizeof(servaddr));//将服务器所在地址绑定到listenfd套接字上

	Listen(listenfd, LISTENQ);//进行监听

	Signal(SIGCHLD, sig_chld);	/* must call waitpid() *///捕获SIGCHLD,依次杀死defunct(zombie)进程

	for (; ; ) {
		clilen = sizeof(cliaddr);
		if ((connfd = accept(listenfd, (SA *)&cliaddr, &clilen)) < 0) {
			if (errno == EINTR)//处理accept过程中发生中断情况
				continue;		/* back to for() */
			else
				err_sys("accept error");
		}

		if ((childpid = Fork()) == 0) {	/* child process */
			Close(listenfd);	/* close listening socket */
			str_echo(connfd);	/* process the request */
			exit(0);
		}
		Close(connfd);			/* parent closes connected socket */
	}
}
5、客户端程序
#include	"unp.h"
//--------------------------------------------------------
//客户端
//--------------------------------------------------------

void str_cli(FILE *fp, int sockfd) {//此函数存在一个巨大BUG,不能单纯阴塞在套接字和用户输入这两个源中某中特定源的输入,需要用select或poll函数重写
	char	sendline[MAXLINE], recvline[MAXLINE];

	while (Fgets(sendline, MAXLINE, fp) != NULL) {//一般情况下,会阻塞在此,等待用户输入

		Writen(sockfd, sendline, strlen(sendline));//从标准输入中读入一行文本

		if (Readline(sockfd, recvline, MAXLINE) == 0)//读出文本内容
			err_quit("str_cli: server terminated prematurely");

		Fputs(recvline, stdout);//将recvline写到标准输出上
	}
}
int
main(int argc, char **argv)
{
	int					sockfd;
	struct sockaddr_in	servaddr;

	if (argc != 2)
		err_quit("usage: tcpcli <IPaddress>");

	sockfd = Socket(AF_INET, SOCK_STREAM, 0);

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(SERV_PORT);
	Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

	Connect(sockfd, (SA *)&servaddr, sizeof(servaddr));

	str_cli(stdin, sockfd);		/* do it all *///此处阻塞存在问题,具体见子函数分析

	exit(0);
}

猜你喜欢

转载自blog.csdn.net/tt_love9527/article/details/80148640