Linux 套接字编程 - TCP连接基础
第五章的内容,实现一个echo服务器和对应的客户端,主要收获:
0. TCP socket编程主要基本步骤
1. SIGCHLD信号含义(子进程退出时向父进程发送,提醒父进程对其状态信息进行一个获取),waitpid 和 wait在使用上的差异,前者可以配置参数设定为非阻塞方式调用,更加灵活。
2. 信号处理函数与其过程(尤其是信号发生后不列队这个性质),相同的信号多次发生(间隔非常接近的话)可能仅会调用一次信号处理函数
3. 信号处理对慢系统(阻塞)调用如accept等的影响(如果信号处理设置时没有置SA_RESTART),accept被中断后直接返回EINTR,而不是一个合法的socket fd,所以对一些调用的错误值检测并不是杞人忧天
4. 僵尸进程,只要父进程调用了wait*函数获取了已死子进程的状态信息后,它就消失了。但如果父进程产生了超多子进程,而他们有很快的死掉,然后父进程也不调用wait*函数,那么会使得pid号不够用
服务端程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <unistd.h>
#include <signal.h> #include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h> #define SOCKET_BACKLOG 100
#define SERVER_PORT 1234
#define BUF_SIZE 256 void echo(int fd); void setup_signal_handler(); int main() {
/* setup SIGCHLD handler */
setup_signal_handler(); /* define socket address */
struct sockaddr_in server = {};
server.sin_family = AF_INET;
server.sin_port = htons( SERVER_PORT ); /* define socket file descriptor */
int server_fd = socket(AF_INET, SOCK_STREAM, ); /* bind socket file descriptor to the socket address */
bind(server_fd, (struct sockaddr *)&server, sizeof(server)); /* listen on this socket file descriptor */
listen( server_fd, SOCKET_BACKLOG ); /* define socket struct/file descriptor used to present remote peer(client) */
struct sockaddr_in client = {};
int client_fd;
int client_sockaddr_len = ; /* application send buffer */
char buffer[BUF_SIZE]; while () {
printf("server ready to accept\n");
client_fd = accept(server_fd, (struct sockaddr *)&client, &client_sockaddr_len);
if (client_fd < ) {
/* if SA_RESTART is not set in setup_signal_handler and
* then when process is interrupted by SIGCHLD
* the accept() will return EINTR instead of a valid socket fd
*/
printf("server accept error!\n");
continue;
}
if (fork() == ) {
close(server_fd);
printf("child process start pid(%d)\n", getpid()); echo(client_fd); printf("child process exit pid(%d)\n", getpid());
exit();
}
close(client_fd);
} return ;
} void echo(int fd) {
int n;
char buffer[BUF_SIZE];
while ((n = read(fd, buffer, BUF_SIZE)) > ) {
write(fd, buffer, n);
}
} void signal_child_handler(int signo) {
pid_t pid;
int stat; /* pid = wait(&stat);
* signal is not queued, many child process exits
* may just cause one signal handle process
* so we should use waitpid() in a row instead of a single wait()
* to collect child process information
*/
while ((pid = waitpid(-, &stat, WNOHANG)) > ) {
printf("child process pid(%d) terminated\n", pid);
}
} void setup_signal_handler() {
struct sigaction act, old_act; act.sa_handler = signal_child_handler;
sigemptyset(&act.sa_mask);
act.sa_flags = ;
#ifdef SA_RESTART
act.sa_flags |= SA_RESTART;
printf("SA_RESTART\n");
#endif
if (sigaction(SIGCHLD, &act, &old_act) < ) {
printf("setup SIGCHLD Failed.");
}
}
客户端程序:
#include <unistd.h> #include <stdio.h>
#include <string.h>
#include <stdlib.h> #include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h> #define SERVER_PORT 1234
#define SERVER_IP "127.0.0.1" #define BUF_SIZE 256 void send_echo(FILE* fp, int fd); int main() {
int sockfd = socket(AF_INET, SOCK_STREAM, ); struct sockaddr_in server_addr = {};
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT); inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr); connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)); send_echo(stdin, sockfd); return ;
} void send_echo(FILE* fp, int fd) {
char send_buf[BUF_SIZE] = {};
char recv_buf[BUF_SIZE] = {}; int readn = ;
int writen = ; while(fgets(send_buf, BUF_SIZE, fp) != NULL) {
if ((writen = write(fd, send_buf, strlen(send_buf) + )) < ) {
printf("1st write error\n");
break;
} else {
printf("1st write ok\n");
} sleep(); if ((writen = write(fd, "(test)", strlen("(test)") + )) < ) {
printf("2nd write error\n");
break;
} else {
printf("2nd write ok\n");
} sleep(); if ((readn = read(fd, recv_buf, BUF_SIZE)) < ) {
printf("read error\n");
break;
} else if (readn == ) {
printf("read EOF\n");
break;
}
fputs(recv_buf, stdout);
}
printf("client exit\n");
}
Linux 套接字编程 - TCP连接基础的更多相关文章
- Linux 套接字编程中的 5 个隐患(转)
本文转自IBM博文Linux 套接字编程中的 5 个隐患. “在异构环境中开发可靠的网络应用程序”. Socket API 是网络应用程序开发中实际应用的标准 API.尽管该 API 简单,但是开发新 ...
- C++网络套接字编程TCP和UDP实例
原文地址:C++网络套接字编程TCP和UDP实例作者:xiaojiangjiang 1. 创建一个简单的SOCKET编程流程如下 面向有连接的套接字编程 服务器: 1) 创建套接字(so ...
- linux 套接字编程入门--Hello World
下述代码是linux套接字编程的入门代码.分为服务端和客户端源码. 服务端代码的主要流程是绑定ip地址和端口号建立套接字,等待客户端发起访问.接受客户端请求之后,向客户端发送字符串"hell ...
- (转载)Linux 套接字编程中的 5 个隐患
在 4.2 BSD UNIX® 操作系统中首次引入,Sockets API 现在是任何操作系统的标准特性.事实上,很难找到一种不支持 Sockets API 的现代语言.该 API 相当简单,但新的开 ...
- Linux 套接字编程中的 5 个隐患
http://www.ibm.com/developerworks/cn/linux/l-sockpit/ 在 4.2 BSD UNIX® 操作系统中首次引入,Sockets API 现在是任何操作系 ...
- Linux套接字编程
网络中的进程是如何通信的? 在网络中进程之间进行通信的时候,那么每个通信的进程必须知道它要和哪个计算机上的哪个进程通信.否则通信无从谈起!在本地可以通过进程PID来唯一标识一个进程,但是在网络中这是行 ...
- Linux 套接字编程中要注意的细节
隐患 1.忽略返回状态 第一个隐患很明显,但它是开发新手最容易犯的一个错误.如果您忽略函数的返回状态,当它们失败或部分成功的时候,您也许会迷失.反过来,这可能传播错误,使定位问题的源头变得困难. 捕获 ...
- Linux 套接字编程 - select
select 可以感知文件表述符集合中的变化,如果办fd0(即标准输入)放入select的read fd set,发现只有按回车的时候select才会返回.查了下要把终端的缓冲大小设为1,这样就能实现 ...
- 【转】Linux 套接字编程中的 5 个隐患
地址:请点击这里
随机推荐
- The server of Nginx(一)——Nginx基础及静态网站的构建
一.Nginx介绍 火了半边天的Nginx和Apache一样也是Web服务器,专为性能优化而开发,也可以像Squid一样做反向代理,或者邮件代理等许多用途,并有windows的移植版,其最知名的优点是 ...
- 《Java并发编程实战》第十章 避免活跃性危急 读书笔记
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/love_world_/article/details/27635333 一.死锁 所谓死锁: 是指两 ...
- String Reduction问题分析
问题描述: Given a string consisting of a,b and c's, we can perform the following operation: Take any two ...
- Android TextUtils工具类的使用
1.采用File类,在指定目录下读写数据 java后台代码为: (1)向app的/data/data/com.example.lucky.helloworld目录下写入文本(涉及IO的读写操作) pa ...
- 应大数据时代而写了个磁力搜索的网页- WWW.MOVIH.COM 磁力
应大数据时代而写了个磁力搜索的网页- 索马里搜索磁力 http://www.,movih.com/ BT磁力示例网站:WWW.MOVIH.COM 采用分布式架构: JAVA系统:JBOSS7+EJB3 ...
- bzoj3224 普通平衡树 splay模板
题目传送门 题目大意:完成一颗splay树. 思路:模板题,学着还是很有意思的. 学习splay树:蒟蒻yyb 该题模板:汪立超 #include<bits/stdc++.h> #defi ...
- MBR为什么不支持3T硬盘
MBR,全称为Master Boot Record,即硬盘的主引导记录.(是管理硬盘分区的一种模式.升级版是GPT) MBR保存在硬盘的第1个扇区(即硬盘的0柱面.0磁头.1扇区).它由三个部分组成, ...
- Oracle KEEP的用法
[摘录自] http://blog.itpub.net/12932950/viewspace-687036/ http://flyfx.iteye.com/blog/1994993 聚合函数MIN, ...
- Flask项目出现html文件无法自动补全
默认情况下我们使用Pycharm专业版创建一个Flask项目时就会自动创建一个简单的项目结构,Pycharm会自动关联起文件的语法,模版等.而自己手动创建的文件并没有关联起来.这就会出现上面说的无法补 ...
- Bloom filter和Counting bloom filter
Bloom filter原理: https://en.wikipedia.org/wiki/Bloom_filter 推导过程结合博客: https://blog.csdn.net/jiaomeng/ ...