TCP客户与服务器进程之间发生的重大事件时间表

TCP服务器

socket() --- bind() --- listen() --- accept() --- read() --- write --- read() --- close

TCP客户

socket() --- connect() --- write() --- read()  --- close()

套接字函数简介

int socket(int family, int type, int protocol);

指定要用的通信协议类型

int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);

客户用connect()来建立与TCP服务器的连接

int bind(int sockfd, const struct sockaddr *myaddr, scoklen_t addrlen);

把一个本地协议地址赋予一个套接字

int listen(int sockfd, int backlog);

设置套接字为被动套接字,指示内核接收向该套接字的连接请求

int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);

由TCP服务器调用, 用来从已完成连接队列队头返回下一个已完成连接

pid_t fork(void);

产生子进程

int close(int sockfd);

关闭套接字, 并终止TCP连接

典型的并发服务器程序轮廓

  1. pid_t pid;
  2. int listenfd, connfd;
  3. listenfd=Socket(...);
  4. Bind(listenfd, ...);
  5. Listen(listenfd,LISTENQ);
  6. for(;;){
  7. connfd=Accept(listenfd, ...);
  8. if((pid=Fork())==0){//如果是子进程
  9. Close(listenfd);//子进程关闭其监听套接字
  10. doit(connfd);//处理需求
  11. Close(connfd);//关闭子进程的已连接套接字
  12. exit(0);//子进程终止
  13. }
  14. Close(connfd);//父进程关闭已连接套接字
  15. }

TCP echo服务器程序

  1. #include "unp.h"
  2. #include <time.h>
  3. void srv_echo(int sockfd)
  4. {
  5. ssize_t n;
  6. char buf[1000];
  7. again:
  8. while((n=read(sockfd,buf,1000))>0)
  9. Writen(sockfd,buf,n);
  10. if(n<0 && errno==EINTR)
  11. goto again;
  12. else if(n<0)
  13. err_sys("srv_echo: read error");
  14. }
  15. int
  16. main(int argc,char ** argv)
  17. {
  18. int listenfd, connfd;
  19. pid_t childpid;
  20. socklen_t clilen;
  21. struct sockaddr_in cliaddr, servaddr;
  22. char buff[1000];
  23. listenfd=Socket(AF_INET, SOCK_STREAM, 0);
  24. bzero(&servaddr, sizeof(servaddr));
  25. servaddr.sin_family=AF_INET;
  26. servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
  27. servaddr.sin_port=htons(1234);
  28. Bind(listenfd, (SA*) &servaddr, sizeof(servaddr));
  29. Listen(listenfd, 100);
  30. for(;;){
  31. clilen=sizeof(cliaddr);
  32. connfd=Accept(listenfd, (SA*) &cliaddr, &clilen);
  33. printf("connection from %s , port %d\n",
  34. inet_ntop(AF_INET,&cliaddr.sin_addr, buff, sizeof(buff)),
  35. ntohs(cliaddr.sin_port));
  36. if((childpid=Fork())==0){
  37. Close(listenfd);
  38. srv_echo(connfd);
  39. exit(0);
  40. }
  41. Close(connfd);
  42. }
  43. }

TCP echo客户端程序

  1. #include "unp.h"
  2. void cli_echo(FILE *fp, int sockfd)
  3. {
  4. char sendline[1000], recvline[1000];
  5. while(Fgets(sendline,1000, fp)!=NULL){
  6. Writen(sockfd, sendline, strlen(sendline));
  7. if(Readline(sockfd, recvline, 1000)==0)
  8. err_quit("cli_echo: server terminated prematurely");
  9. Fputs(recvline, stdout);
  10. }
  11. }
  12. int
  13. main(int argc, char **argv)
  14. {
  15. int sockfd;
  16. struct sockaddr_in servaddr;
  17. if(argc!=2)
  18. err_quit("usage: tcpcli <IPaddress>");
  19. sockfd=Socket(AF_INET, SOCK_STREAM, 0);
  20. bzero(&servaddr, sizeof(servaddr));
  21. servaddr.sin_family=AF_INET;
  22. servaddr.sin_port=htons(1234);
  23. Inet_pton(AF_INET,argv[1], &servaddr.sin_addr);
  24. Connect(sockfd, (SA*) &servaddr, sizeof(servaddr));
  25. cli_echo(stdin,sockfd);
  26. exit(0);
  27. }

这一章的API讲解非常有逻辑性, 讲解的过程可以看到这样设计的合理性

4.5 listen函数

当一个客户的SYN到达, 若服务器的相应监听套接字维护的队列已经满了,  TCP就会忽略该分节, 也就是不发送RST. (这里的TCP指的是实现TCP的内核)

之所以这样设计有两点理由:

(1)这种情况是暂时的, TCP的正常重传机制会处理这个问题

(2)客户无法区分这个RST意思是 "该端口没有服务器在监听" 还是 "该端口有服务器在监听, 不过队列已满"

第四章 基本TCP套接字编程 第五章 TCP客户/服务器程序实例的更多相关文章

  1. 【UNIX网络编程(四)】TCP套接字编程具体分析

    引言: 套接字编程事实上跟进程间通信有一定的相似性,可能也正由于此.stevens这位大神才会将套接字编程与进程间的通信都归为"网络编程",并分别写成了两本书<UNP1> ...

  2. 基本套接字编程(1) -- tcp篇

    1. Socket简介 Socket是进程通讯的一种方式,即调用这个网络库的一些API函数实现分布在不同主机的相关进程之间的数据交换. 几个定义: (1)IP地址:即依照TCP/IP协议分配给本地主机 ...

  3. UNP学习笔记1——基本TCP套接字编程

    1 套接字地址结构 大多数套接字函数都需要一个指向套接字地址结构的指针作为参数.每个协议族都定义了自己的套接字结构.这些套接字的结构以sockaddr_开头,以每个协议族唯一的后缀名结尾. 1.1 I ...

  4. TCP套接字编程模型及实例

    摘要:     本文讲述了TCP套接字编程模块,包括服务器端的创建套接字.绑定.监听.接受.读/写.终止连接,客户端的创建套接字.连接.读/写.终止连接.先给出实例,进而结合代码分析. PS:本文权当 ...

  5. UNP学习笔记(第四章 基本TCP套接字编程)

    本章讲解编写一个完整的TCP客户/服务器程序所需要的基本套接字函数. socket函数 #include <sys/socket.h> int socket(int family,int ...

  6. unix网络编程第四章----基于TCP套接字编程

    为了执行网络I/O操作.进程必须做的第一件事情就是调用Socket函数.指定期待的通信协议 #include<sys/socket.h> int socket(int family,int ...

  7. UNP——第四章,TCP套接字编程

    1.socket 函数 首先被调用的函数,用于选择通信协议. socket调用成功后,得到的套接字为主动套接字CLOSED状态. PF 和 AF 的关系 PF的是协议族,AF是地址族,理论上一个PF包 ...

  8. 初探网络编程--TCP套接字编程演示

    今天看了一下<计算机网络:自顶向下方法>,也就是计算机网络的教材的应用层一章,决定实现以下后面的Java C/S应用程序的例子,用来演示TCP和UDP套接字编程. 程序流程如下: 1.一台 ...

  9. TCP套接字编程

    一.套接字(socket)函数 图1给出了在一个TCP客户与服务器通信的流程.服务器首先启动,稍后某个客户启动,它试图连接到服务器.假设客户给服务器发送一个请求,服务器处理该请求,并且给客户发回一个相 ...

随机推荐

  1. vue进入页面时不在顶部,检测滚动返回顶部按钮

    这里是本小白使用时遇到的问题及个人使用的方法可能并不完美. 1.监测浏览器滚动条滚动事件及滚动距离 dmounted() { window.addEventListener("scroll& ...

  2. webpack4 + ejs 构建多页应用

    目录结构 ├─build webpack配置目录 │ ├─plugins.js │ ├─rules.js │ ├─transfromAssets.js //简单的一个插件,处理路径问题 │ └─web ...

  3. flask打包安装文件

    如果在一台新的电脑需要运行项目的时候,这时候就需要将项目项目所用到的模块都导出来 依赖文件生成pip freeze > requirements.txt 执行该命令会在项目根目录下生成一个 re ...

  4. 铰链joints

    Fixed Joint原理像阶层里的父子结构.关节会将对象锁在一个世界坐标或者锁在一个连接的刚体. 固定关节可以设定断裂力道(Break Farce)和断裂扭力(Break torque),破坏关节所 ...

  5. ASP.NET使用window.event.keycode来获取按下的键盘值!

    window.event.keycode-获取按下的键盘值 这里只列出了一些较常用的键盘值更加详细的键盘值请访问此人博客:https://www.cnblogs.com/z-sm/p/3597592. ...

  6. Android笔记 (一) 第一次接触Android

    1.下载android SDK 访问http://developer.android.com/ →  GET THE SDK →  Installing the Android SDK →  STAN ...

  7. [leetcode]存在重复

    题目描述: 给定一个整数数组,判断是否存在重复元素. 如果任何值在数组中出现至少两次,函数返回 true.如果数组中每个元素都不相同,则返回 false. 示例 1: 输入: [1,2,3,1] 输出 ...

  8. Linux命令——source

    参考:What does 'source' do? 前言 当我们修改了/etc/profile文件,并想让它立刻生效,而不用重新登录,就可以使用source命令,如source /etc/profil ...

  9. redis高可用之sentinel哨兵

    一,单实例模式 当系统中只有一台redis运行时,一旦该redis挂了,会导致整个系统无法运行. 二,主从模式 由于单台redis出现单点故障,就会导致整个系统不可用,所以想到的办法自然就是备份.当一 ...

  10. osi七层网络模型(一)

    在网络中OSI分为七层网络模型,怎么理解七层模型呢?简单理解我们的手机都有手机壳.屏幕.摄像头.电池.芯片等很多原件,每个原件都是由不同的 厂家生产,最终组装成了一部功能完整的手机,同样,在网络中,也 ...