UNPv13:#第5章#TCP客户/服务器程序示例
时间:2022-05-03
本文章向大家介绍UNPv13:#第5章#TCP客户/服务器程序示例,主要内容包括Code、服务器进程终止、SIGPIPE信号、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
Code
//server.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
void sig_chld(int signo)
{
pid_t pid;
int stat;
while((pid = waitpid(-1, &stat, WNOHANG)) > 0)
printf("child %d terminatedn", pid);
return;
}
int main(int argc, char* argv[])
{
int listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(listenfd == -1)
{
perror("function socket error :");
exit(-1);
}
struct sockaddr_in serveraddr;
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons(atoi(argv[1]));
if(bind(listenfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) == -1)
{
perror("function bind error : ");
exit(-1);
}
if(listen(listenfd, 5) == -1)
{
perror("function listen error : ");
exit(-1);
}
struct sigaction act, oact;
act.sa_handler = sig_chld;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if(sigaction(SIGCHLD, &act, &oact) == -1)
{
perror("function sigaction error : ");
exit(-1);
}
int connfd;
struct sockaddr_in clientaddr;
socklen_t clientlen;
while(1)
{
clientlen = sizeof(clientaddr);
connfd = accept(listenfd, (struct sockaddr *)&clientaddr, &clientlen);
if(connfd == -1)
{
if(errno == EINTR)
continue;
perror("function accept error : ");
exit(-1);
}
if(fork() == 0)
{
if(close(listenfd) == -1)
{
perror("function close error : ");
exit(-1);
}
char buf[1024];
int len;
AGAIN:
while((len = read(connfd, buf, 1024)) > 0)
write(connfd, buf, len);
if(len < 0 && errno == EINTR)
goto AGAIN;
else if(len < 0)
{
perror("function read error : ");
exit(1);
}
}
else
{
if(close(connfd) == -1)
{
perror("function close error : ");
exit(-1);
}
}
}
return 0;
}
//client.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char* argv[])
{
int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sockfd == -1)
{
perror("function socket error : ");
exit(-1);
}
struct sockaddr_in serveraddr;
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
switch(inet_pton(AF_INET, argv[1], &serveraddr.sin_addr))
{
case 0:
perror("function inet_pton error (input invalid) : ");
exit(-1);
break;
case 1:
//successed
break;
default:
perror("function inet_pton error : ");
exit(-1);
break;
}
serveraddr.sin_port = htons(atoi(argv[2]));
connect(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
char buf[1024];
while(fgets(buf, 1024, stdin) != NULL)
{
write(sockfd, buf, strlen(buf));
if(read(sockfd, buf, 1024) == 0)
{
perror("server terminated");
exit(0);
}
fputs(buf, stdout);
}
return 0;
}
服务器进程终止
客户TCP收到FIN只是表示服务器进程已关闭连接的服务端,从而不再往其中发送任何数据而已。FIN的接收并没有告知客户TCP服务器进程已经终止。
SIGPIPE信号
当一个进程向某个已收到RST的套接字执行写操作时,内核向该进程发送一个SIGPIPE信号。该信号默认行为是终止进程。不论该进程捕获该信号并从其信号处理函数返回,还是简单的忽略该信号,写操作都将返回EPIPE。 第一次写操作引发RST,第二次写引发SIGPIPE信号。写一个已接收FIN的套接字不成问题,但写一个已接收了RST的套接字则是一个错误。
- 最简单最常用的LinearLayout线性布局
- 漏洞科普:你对弱口令重视吗?
- 自定义View简单使用
- 正确姿势:如何调戏蹭网者
- 当我们讨论流畅度的时候,我们究竟在说什么?
- ImageButton和ZoomButton使用大全
- Android 插件化突破应用市场无法上广告的问题
- ImageView的属性和方法大全
- sharedpreferences如何保存对象
- Android:全面解析熟悉而陌生 的 Application 类使用
- ToggleButton和Switch使用大全
- Android 无需权限显示悬浮窗, 兼谈逆向分析 App
- android数据保存之greendao
- CheckBox和RadioButton使用大全
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 简单谈谈centos7中配置php
- Linux动态链接库的使用
- Linux下部署springboot项目的方法步骤
- Linux、CentOS下安装zip与unzip指令功能(服务器)
- Linux上查看用户创建日期的几种方法总结
- 详解基于Linux的LVM无缝磁盘水平扩容
- CentOS平台实现搭建rsync远程同步服务器的方法
- CentOS 8设置自动更新的完整步骤
- linux 网络编程 socket选项的实现
- Ubuntu16.04安装Jenkins的方法图文详解
- leetcode树之对称二叉树
- linux 上在指定时间段内每隔多少分钟自动执行任务计划crontab
- 详解如何使用Spark和Scala分析Apache访问日志
- Centos 7.4中的远程访问控制的实现方法
- Linux查找特定程序whereis实例详解