不多说了,先上个图:

从上面的图中可以看出来,基于TCP协议进行通讯可以大致分成以下几个阶段:

1. 首先是在服务器端, TCP Sever调用socket(), bind(), listen()完成初始化。然后调用accept()阻塞等待,处于监听端口的状态。

2. 客户端调用socket()初始化后,调用connect()发出SYN段并阻塞等待服务器应答,服务器应答一个SYN-ACK段,客户端收到后从connect()返回,

同时应答一个ACK段,服务器收到后从accept()返回。这也就是传说中的TCP三次握手,如下图所示:

TCP 三次握手有一种形象的理解,大家去买手机的时候总要试试手机的通话功能吧, 这时你会走远和你的朋友通话看看质量是否可靠,一般是不是这样:

  • 喂, 听的到吗? (Client)
  • 听的到, 你听的到吗 ? (Server)
  • 嗯, 我也听的到 (Client)

那么就能保证通话质量是OK的, TCP协议也是一样, 通过规定了双方的应答保证了连接的可靠性。

3. 完成三次握手(TCP three way handshake ) TCP Server与TCP Client就建立起了可靠的连接。此后就是Server与Client 数据传输的过程了。因此,服务器从accept()返回

后立刻调用read(),读socket就像读管道一样,如果没有数据到达就阻塞等待,这时客户端调用write()发送请求给服务器,服务器收到后从read()返回,对客户端的请求进行处理,在

此期间客户端调用read()阻塞等待服务器的应答,服务器调用write()将处理结果发回给客户端,再次调用read()阻塞等待下一条请求,客户端收到后从read()返回,发送下一条请

求,如此循环下去。

4. 关闭连接的过程。 如果客户端没有更多的请求了,就调用close()关闭连接,就像写端关闭的管道一样,服务器的read()返回0,这样服务器就知道客户端关闭了连接,也调用

close()关闭连接。注意,任何一方调用close()后,连接的两个传输方向都关闭,不能再发送数据了。如果一方调用shutdown()则连接处于半关闭状态,仍可接收对方发来的数

据。

贴一个简易的TCP Sever与TCP Client的实现:

 /***********************************************************/
/* Copyright (C) SA14226214, USTC, 2014-2015 */
/* */
/* FILE NAME : server.c */
/* PRINCIPAL AUTHOR : GaoZhipeng */
/* SUBSYSTEM NAME : lab1 */
/* MODULE NAME : server */
/* LANGUAGE : C */
/* TARGET ENVIRONMENT : ANY */
/* DATE OF FIRST RELEASE : 2014/12/01 */
/* DESCRIPTION : This is a server program */
/***********************************************************/ /*
*Revision log:
*
*Ceated by GaoZhipeng, 2014/12/01
*
*/ #include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h> #define MAXLINE 80
#define SERV_PORT 8000 int main(void)
{
struct sockaddr_in servaddr, cliaddr;
socklen_t cliaddr_len;
int listenfd, connfd;
char recv_buf[MAXLINE];
char *send_buf;
char str[INET_ADDRSTRLEN];
int i, n; listenfd = socket(AF_INET, SOCK_STREAM, ); bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT); bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
listen(listenfd,); printf("Accepting connections ...\n");
cliaddr_len = sizeof(cliaddr);
connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
while()
{
n = read(connfd, recv_buf, MAXLINE);
if(n == )
{
printf("the client has been closed , please restart again\n");
break;
}
printf("received from %s at PORT %d ",(char *)inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)), ntohs(cliaddr.sin_port));
//print the recv_buf on the terminal
write(STDOUT_FILENO, recv_buf, n);
printf("\n"); send_buf = "你好世界";
write(connfd, send_buf, strlen(send_buf));
}
close(connfd); }
 /***********************************************************/
/* Copyright (C) SA14226214, USTC, 2014-2015 */
/* */
/* FILE NAME : server.c */
/* PRINCIPAL AUTHOR : GaoZhipeng */
/* SUBSYSTEM NAME : lab1 */
/* MODULE NAME : server */
/* LANGUAGE : C */
/* TARGET ENVIRONMENT : ANY */
/* DATE OF FIRST RELEASE : 2014/12/01 */
/* DESCRIPTION : This is a server program */
/***********************************************************/ /*
*Revision log:
*
*Ceated by GaoZhipeng, 2014/12/01
*
*/ #include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h> #define MAXLINE 80
#define SERV_PORT 8000 int main(int argc, char *argv[])
{
struct sockaddr_in servaddr;
char buf[MAXLINE];
int sockfd, n; sockfd = socket(AF_INET, SOCK_STREAM, ); bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
servaddr.sin_port = htons(SERV_PORT); connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); printf("input you message (q to exit): "); //ŽÓ±ê׌ÊäÈëÉ豞ÖжÁÈ¡×Ö·ûŽ®ÐŽÈëbuf
while(fgets(buf, MAXLINE, stdin) != NULL) {
if(buf[] == 'q' && strlen(buf) == )
{
break;
}
write(sockfd, buf, strlen(buf)); n = read(sockfd, buf, MAXLINE);
if(n == )
{
printf("the connect side has been closed. please run it again\n");
exit();
}
write(STDOUT_FILENO, "Response from server : ", sizeof("Response from server : "));
write(STDOUT_FILENO, buf, n);
printf("\ninput you message (q to exit): ");
}
close(sockfd);
return ;
}

一个简单的MakeFile :

/*           makefile               */
all :
gcc server.c -o server
gcc client.c -o client clean :
rm server client

基于TCP协议的网络通讯流程的更多相关文章

  1. 闲来无事,写个基于TCP协议的Socket通讯Demo

    .Net Socket通讯可以使用Socket类,也可以使用 TcpClient. TcpListener 和 UdpClient类.我这里使用的是Socket类,Tcp协议. 程序很简单,一个命令行 ...

  2. 基于TCP协议的网络编程

    TCP通信协议是一种可靠的传输层协议,它在通信的两端各建立一个Socket,从而在通信的两端之间形成虚拟网络链路.一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信.Java使用Socke ...

  3. 学习笔记——网络编程3(基于TCP协议的网络编程)

    TCP协议基础 IP协议是Internet上使用的一个关键协议,它的全称是Internet Protocol,即Internet协议,通常简称IP协议.   使用ServerSocket创建TCP服务 ...

  4. Java网络编程三--基于TCP协议的网络编程

    ServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,它将一直处于等待状体 Socket accept():如果接收到客户端的连接请求,该方法返回一个与客户端对应Socket ...

  5. 浅析C#基于TCP协议的SCOKET通信

    TCP协议是一个基本的网络协议,基本上所有的网络服务都是基于TCP协议的,如HTTP,FTP等等,所以要了解网络编程就必须了解基于TCP协议的编程.然而TCP协议是一个庞杂的体系,要彻底的弄清楚它的实 ...

  6. Learning-Python【28】:基于TCP协议通信的套接字

    什么是 Socket Socket 是应用层与 TCP/IP 协议通信的中间软件抽象层,它是一组接口.在设计模式中,Socket 其实就是一个门面模式,它把复杂的 TCP/IP 协议族隐藏在 Sock ...

  7. [网络编程之Socket套接字介绍,套接字工作流程,基于TCP协议的套接字程序]

    [网络编程之Socket套接字介绍,套接字工作流程,基于TCP协议的套接字程序] 为何学习socket套接字一定要先学习互联网协议: 1.首先:要想开发一款自己的C/S架构软件,就必须掌握socket ...

  8. 网络编程----socket介绍、基于tcp协议的套接字实现、基于udp协议的套接字实现

    一.客户端/服务器架构(C/S架构)                                                即C/S架构,包括: 1.硬件C/S架构(打印机) 2.软件C/S架 ...

  9. 网络编程之TCP三次握手与四次挥手、基于TCP协议的套接字编程

    目录 TCP三次握手和四次挥手 背景描述 常用的熟知端口号 TCP概述 TCP连接的建立(三次握手) TCP四次挥手 如果已建立连接,客户端突然断开,会怎么办呢? 基于TCP协议的套接字编程 什么是S ...

随机推荐

  1. 专题《一》 mysql优化

    从今天开始,在这里记录面试会问的问题,针对java高级开发,架构师方向. 1.数据库设计要合理.开发经验不同  设计表水平不同  影响后面操作 三范式:1------------原子约束,每列不可分割 ...

  2. 关于使用memcached提高并发的文章,很有用

    http://blog.csdn.net/ywh147/article/details/9385137 http://phl.iteye.com/category/292555 memcached 解 ...

  3. springboot+shiro+cas实现单点登录之cas server搭建

    CAS是YALE大学发起的一个开源项目,旨在为web应用系统提供一种可靠的单点登录方法.它主要分为client和server端,server端负责对用户的认证工作,client端负责处理对客户端受保护 ...

  4. webpack相关插件

    webpack-merge:开发环境和生产环节的webpaak配置文件的配置合并 file-loader:编译写入文件,默认情况下生成文件的文件名是文件名与MD5哈希值的组合 vue-laoder:编 ...

  5. 《移动Web前端高效开发实战》笔记4--打造单页应用SPA

    路由是一个单页应用的核心,大部分前端框架都实现了一个复杂的路由库,包括动态路由,路由钩子,组件生命周期甚至服务器端渲染等复杂的功能.但是对于前端开发者而言,路由组件的核心是URL路径到函数的映射,了解 ...

  6. HBase数据模型(1)

    HBase数据模型(1) HBase数据模型(2) 1.0 HBase的特性 Table HBase以表(Table)的方式组织数据,数据存储在表中. Row/Column 行(Row)和列(Colu ...

  7. [ros]编译ORBSLAM2时候,ros路径问题

    CMake Error at CMakeLists.txt:2 (include): include could not find load file: /core/rosbuild/rosbuild ...

  8. linux命令之文本查看

    vi掌握练习: 英文文档,相同的单词复制粘贴光标移动编辑等操作: cat:显示文件所有内容,小文件查看时使用. 缺点:文件大时不方便查看,文件很大时,会抢占系统资源,会出现命令崩溃. [zyj@loc ...

  9. POJ 2288 Islands and Bridges (状压DP,变形)

    题意: 给一个无向图,n个点m条边,每个点有点权,要求找到一条哈密顿路径,使得该路径的f(path)值最大.输出f值,若有多条最大f值的路径,输出路径数量. f值由如下3点累加而来: (1)所有点权之 ...

  10. python基础教程总结2——字符串

    1.基本操作 序列操作:索引,分片,乘法,判断成员资格,长度,最值...... 注:字符串不可变,分片赋值不合法 2.字符串格式化 模板 格式化字符串时,Python使用一个字符串作为模板.模板中有格 ...