TCP/IP :
      TCP/IP:在网络通信中,TCP/IP是主流协议()
      应用层:用户自定义的协议(HTTP,EMAIL,),用于用户之间数据的传送
      传输层:(传输控制:TCP,UDP)负责点对点之间连接建立,传输控制协议的指定() 
      网络层:用于查找路由(查找)
      网络接口层 : 将二进制转换为数据帧。

TCP帧:
   [源端号][目的端口]     
   [   顺序号       ]
   [TCP包头长][URG/ACK/PSH/RST/SYN/FIN][窗口大小]
   [检验和][紧急指针]
   [可选项          ]
   [数据包]

TCP:面向连接,安全可靠有状态的传输协议。(比UDP效率差)
           怎样连接:三次握手简述(确保双方一定同时在线)
           A与B建立TCP连接时:首先A向B发SYN(同步请求)
                                                然后B回复SYN+ACK(同步请求应答)
                                                最后A回复ACK确认
           这样TCP的一次连接(三次握手)的过程就建立了!

/**** 下面部分转载自 : 简述TCP的三次握手过程_戴耳机的皮皮熊的博客-CSDN博客_tcp三次握手

TCP握手协议详述 :
           在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接.
           第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
           SYN:同步序列编号(Synchronize Sequence Numbers)
           第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;                                                                                                                                                                      第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手.
           完成三次握手,客户端与服务器开始传送数据

所谓三次握手(Three-Way Handshake)即建立TCP连接,就是指建立一个TCP连接时,需要客户端和服务端总共发送3个包以确认连接的建立。在socket编程中,这一过程由客户端执行connect来触发,整个流程如下图所示:

(1)第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。                                                                                                                                                                  (2)第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。                    (3)第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。                
         SYN攻击:
         在三次握手过程中,Server发送SYN-ACK之后,收到Client的ACK之前的TCP连接称为半连接(half-open connect),此时Server处于SYN_RCVD状态,当收到ACK后,Server转入ESTABLISHED状态。SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server回复确认包,并等待Client的确认,由于源地址是不存在的,因此,Server需要不断重发直至超时,这些伪造的SYN包将产时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络堵塞甚至系统瘫痪。SYN攻击时一种典型的DDOS攻击,检测SYN攻击的方式非常简单,即当Server上有大量半连接状态且源IP地址是随机的,则可以断定遭到SYN攻击了,使用如下命令可以让之现行:                
                                                                #netstat -nap | grep SYN_RECV

上面转载到此处结束 ****/

TCP通信:
       服务器:
              1、创建套接字(打开设备)
                    socket
              2、绑定
                    bind
              3、监听:(设置最大的可连接的线路的数量)
                    listen
              4、等待连接:是一个阻塞函数(注:执行一该函数,则连接一次)
                    int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
                   返回一个套接字,用于在此套接字上收发消息
              5、收到消息
                    recv
              6、关闭套接字                                                                                                                                                                                    注:由于accept和recv都需要阻塞等待,accept返回新的连接描述符。
                      为每一个新的连接请求分配一个新的进程或线程

客户端:
               1、创建套接字(打开设备)
               2、绑定套接字
               3、发出连接请求
                    connect
               4、收发消息
                    send
                    recv
               5、关闭请求
                    close
        传输层:UPD报文SOCK_DGRAM    TCP:流式套接字SOCK_STREAM

注:由于套接字上绑定有端口号,为了防止复用端口号,套接字默认不允许复用。
        API:设备套接字  ---->  setsockopt ( int sock,int level ) ;  level:SOL_SOCKET  对套接字进行设置                                                  socklen_t len=1 ;
        if ( setsockopt ( sock,SOL_SOCKET,SO_REUSEADDR,&len,sizeof(len) ) <0 )
        {
                 perror ( "setsocket fail" ) ;
                 return -1 ;
        }

TCP 服务器的代码实现 :

#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<pthread.h>
//创建锁
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
//子线程:接收链路信息
void* threadfun(void* arg)
{int sock=*(int*)arg;
//解锁pthread_mutex_unlock(&mutex);
//接收消息char buf[100]="";int ilen=0;while(1){ilen=recv(sock,buf,99,0);if(ilen<=0)break;buf[ilen]='\0';printf("收到:%s\n",buf);}close(sock);
}
//TCP:流式套接字
int main()
{
//1创建套接字---打开设备int sock=socket(AF_INET,SOCK_STREAM,0);if(sock<0){perror("socket fail");return -1;}
//修改套接字的网络层:允许IP复用socklen_t len=1;if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&len,sizeof(len))<0){perror("setsocket fail");return -1;}
//2填充结构体并绑定struct sockaddr_in myaddr;   //7979;memset(&myaddr,0,sizeof(myaddr));myaddr.sin_family       =AF_INET;myaddr.sin_port           =htons(7979);myaddr.sin_addr.s_addr        =INADDR_ANY;if(bind(sock,(struct sockaddr*)&myaddr,sizeof(myaddr))==-1){perror("bind fail");return -1;}
//3监听:设置最大的可连接数量,并监听listen(sock,44);
//4等待连接 acceptint newsock=-1;pthread_t tid;while(1){//上锁pthread_mutex_lock(&mutex);newsock=accept(sock,NULL,NULL);if(-1==newsock)break;//创建线程--函数pthread_create(&tid,NULL,threadfun,&newsock);//cout<<"有人连接我了\n"<<endl;}
/*
//5等待该链路上消息到来char buf[100]="";recv(newsock,buf,99,0);printf("收到:%s\n",buf);
*/
//6关闭close(sock);return 0;
}

TCP 客户端的代码实现 :

#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<string.h>
int main()
{
//1创建套接字int sock=socket(AF_INET,SOCK_STREAM,0);    //SOCK_STREAM 流氏sock
//2[绑定:系统为该套接字默认绑定一个空的端口号和一个网卡地址]
//3主动发出连接请求/*填充连接服务器的IP信息*/struct sockaddr_in saddr;memset(&saddr,0,sizeof(saddr)); //填充为0saddr.sin_family      =AF_INET;saddr.sin_port            =htons(7979);saddr.sin_addr.s_addr     =inet_addr("192.168.8.209");if(connect(sock,(struct sockaddr*)&saddr,sizeof(saddr))<0)    //连接{perror("connect fail");return -1;}
//4收发消息char buf[100]="";while(1){scanf("%s",buf);        //客户端可以连续的发送内容send(sock,buf,strlen(buf),0);//strlen 求字符串的长度}
//5关闭close(sock);
}

TCP 的服务器 , 实现从客户端发送信息到服务器 , 服务器接收到文件名后 , 将服务器的文件发送给客户端 ,  从而实现客户端下载服务器的内容 , 如下服务器代码 :

#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<pthread.h>#include<fcntl.h>
//创建锁
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;//子线程:接收链路信息
void* threadfun(void* arg)
{int sock=*(int*)arg;
//解锁pthread_mutex_unlock(&mutex);
//接收消息char buf[100]="";int ilen=0;while(1){char ch[100]="";char chr[1024]="";ilen=recv(sock,buf,99,0);if(ilen<=0)break;buf[ilen]='\0';printf("即将copy文件名%s:",buf);    //buf的内容为客户端发送过来的文件名int fdr=open(buf,O_RDONLY);if(-1==fdr){perror("fail:");return ;}while((ilen=read(fdr,chr,1024))>0)    //将文件读取到 chr[1024] 中{send(sock,chr,strlen(chr),0);     //发送内容给客户端}}close(sock);
}
//TCP:流式套接字
int main()
{
//1创建套接字---打开设备int sock=socket(AF_INET,SOCK_STREAM,0);if(sock<0){perror("socket fail");return -1;}
//修改套接字的网络层:允许IP复用socklen_t len=1;if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&len,sizeof(len))<0){perror("setsocket fail");return -1;}
//2填充结构体并绑定struct sockaddr_in myaddr;   //7979;memset(&myaddr,0,sizeof(myaddr));myaddr.sin_family       =AF_INET;myaddr.sin_port           =htons(7979);myaddr.sin_addr.s_addr        =INADDR_ANY;if(bind(sock,(struct sockaddr*)&myaddr,sizeof(myaddr))==-1){perror("bind fail");return -1;}
//3监听:设置最大的可连接数量,并监听listen(sock,44);
//4等待连接 acceptint newsock=-1;pthread_t tid;while(1){//上锁pthread_mutex_lock(&mutex);newsock=accept(sock,NULL,NULL);if(-1==newsock)break;//创建线程--函数pthread_create(&tid,NULL,threadfun,&newsock);//cout<<"有人连接我了\n"<<endl;}
/*
//5等待该链路上消息到来char buf[100]="";recv(newsock,buf,99,0);printf("收到:%s\n",buf);
*/
//6关闭close(sock);return 0;
}

客户端的实现 :

#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<string.h>
#include<fcntl.h>
int main()
{
//1创建套接字int sock=socket(AF_INET,SOCK_STREAM,0);
//2[绑定:系统为该套接字默认绑定一个空的端口号和一个网卡地址]
//3主动发出连接请求/*填充连接服务器的IP信息*///int pid=fork();char buf[100]="";//if(pid>0)//{struct sockaddr_in saddr;memset(&saddr,0,sizeof(saddr));  //填充为0saddr.sin_family          =AF_INET;saddr.sin_port            =htons(7979);saddr.sin_addr.s_addr =inet_addr("192.168.8.209");if(connect(sock,(struct sockaddr*)&saddr,sizeof(saddr))<0){perror("connect fail");return -1;}
//4收发消息while(1){char bbb[100]="";printf("输入需要拷贝的文件:");    //输入服务器的目录下的文件名scanf("%s",bbb);send(sock,bbb,strlen(bbb),0);//strlen 求字符串的长度 , 将文件名发送给服务器break;}int ilen=0;char aaa[100]="";printf("拷贝为:");scanf("%s",aaa);        //将需要拷贝的文件名命名为 XXXint fdw=open(aaa,O_WRONLY|O_CREAT|O_TRUNC,0644);while(1){ilen=recv(sock,buf,99,0);if(ilen<=0)break;buf[ilen]='\0';write(fdw,buf,ilen);      //写入到文件里面}
//5关闭close(sock);
}

下面是 TCP 的从客户端发送文件名到服务器 , 服务器将文件发送给客户端 , 改进后的代码 , 更加精炼 , 反正比我上面写的好 ,

下面是服务器端的代码 :

#include<stdio.h>
#include<pthread.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<string.h>
#include<fcntl.h>
#include<errno.h>
//拷贝文件信息
struct fileMsg
{char path[255];    //文件名int sock;  //套接字
};pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;//线程函数
void* threadfun(void* arg)
{
//detach线程:当子线程结束,自己在结束之前释放空间,不必需要让父进程来通过join释放pthread_detach(pthread_self());//线程结束,会结束此空间//取出套接字struct fileMsg fm=*(struct fileMsg*)arg;pthread_mutex_unlock(&mutex);
//一边读取文件  一边发送信息char buf[1024]="";int ilen=-1;int fd=open(fm.path,O_RDONLY);if(fd<0){perror("open fail\n");}else{while((ilen=read(fd,buf,1024))>0){if(send(fm.sock,buf,ilen,0)!=ilen)break;}}close(fm.sock);close(fd);
}int main(int argc,char* argv[])
{if(argc<2){perror("arg 不足\n");return -1;}
//判断文件的权限是否存在---读if(access(argv[1],R_OK|F_OK)==-1){fprintf(stderr,"%s %s\n",argv[1],strerror(errno));}//填充结构体:struct fileMsg fm;strcpy(fm.path,argv[1]);int sock=socket(AF_INET,SOCK_STREAM,0);if(sock<0){perror("sock");return -1;}
//修改套接字的属性--允许复用socklen_t s1=sizeof(socklen_t);if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&s1,sizeof(s1))<0){perror("setsock fail");return -1;}struct sockaddr_in myaddr;bzero(&myaddr,sizeof(myaddr));myaddr.sin_family  =AF_INET;myaddr.sin_port       =htons(7979);myaddr.sin_addr.s_addr    =INADDR_ANY;if(bind(sock,(struct sockaddr*)&myaddr,sizeof(myaddr))<0){perror("bind fail");return -1;}if(listen(sock,44)<0){perror("listen fail");return -1;}int newsock=0;pthread_t tid;while(1){//上锁pthread_mutex_lock(&mutex);newsock=accept(sock,NULL,NULL);if(-1==newsock){break;}//填充结构体fm.sock=newsock;//多位同学连接,创建线程if(0!=pthread_create(&tid,NULL,threadfun,&fm)){//解锁pthread_mutex_unlock(&mutex);//关闭套接字close(newsock);continue;}}close(sock);return 0;
}

客户端的代码 :

#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<arpa/inet.h>
#include<fcntl.h>
#include<sys/stat.h>
int main(int argc,char* argv[])
{if(argc<2){perror("参数不足");return -1;}int fd=open(argv[1],O_WRONLY|O_TRUNC|O_CREAT,0644);if(fd<0){perror("open fail");return -1;}int sock=socket(AF_INET,SOCK_STREAM,0);if(sock<0){perror("socket fail");}
//发送连接请求--3次struct sockaddr_in saddr;saddr.sin_family   =AF_INET;saddr.sin_port        =htons(7979);saddr.sin_addr.s_addr =inet_addr("192.168.8.115");if(connect(sock,(struct sockaddr*)&saddr,sizeof(saddr))<0){perror("connect fail\n");return -1;}
//接收int ilen;char buf[1024]="";//从网络上拷贝while((ilen=recv(sock,buf,1024,0))>0){//写入到文件中if(write(fd,buf,ilen)!=ilen){perror("write fail");break;}}   close(sock);close(fd);
}

雨落下雾茫茫,问天涯在何方 《雨下一整晚》

TCP 服务器/客户端(实现下载)相关推荐

  1. TCP服务器客户端编程流程

    TCP服务器客户端编程流程 TCP编程流程 主机字节序列和网络字节序列 套接字地址结构 通用socket地址结构 一般使用会定义一个专用的套接字结构 IP地址转换函数 网络编程接口 TCP服务段代码实 ...

  2. TCP服务器/客户端实例(C/C )

    1.1.Linux下的TCP服务器: #include <stdio.h> #include <stdlib.h> #include <string.h> #inc ...

  3. Python网络编程之TCP服务器客户端(二)

    传输控制协议(官方术语为TCP/IP协议)是互联网的重要组成部分.TCP的第一个版本是在1974年定义的,它建立在网际层协议(IP)提供的数据包传输技术之上.TCP使得应用程序可以使用连续的数据流进行 ...

  4. 【Chat】实验 -- 实现 C/C++下TCP, 服务器/客户端 多人聊天室

    本次实验利用TCP/IP, 语言环境为 C/C++ 利用套接字Socket编程,以及线程处理, 实现Server/CLient 之间多人的聊天系统的基本功能. 结果大致如: 下面贴上代码(参考参考.. ...

  5. tcp服务器客户端状态图

    转载于:https://www.cnblogs.com/rspb/p/4735899.html

  6. python3.6环境下安装gevent,附协程TCP服务器客户端代码

    1.执行 pip3 install gevent 2.报错 importlib._bootstrap' has no attribute 'SourceFileLoader' 3.重新安装pip3 w ...

  7. 多线程 python tcp 图片_Python第四周之网络编程TCP (服务器/客户端; 线程下载图片;线程版服务器和客户端(单人、多人)) UDP...

    # 网络编程 # 计算机网络, 把多台独立自主的计算机,连接到网络,实现资源的共享 # Internet网,(互联网)eniac 1946美国大学第一台电子计算机 # # 一个TCP报文除了包含要传输 ...

  8. java如何实现tcp传输图像_如何在java中实现TCP服务器和TCP客户端传输文件

    我实现了简单的TCP服务器和TCP客户端类,可以从客户端发送消息到服务器,消息将在服务器端转换为大写,但是如何实现从服务器到客户端的传输文件,并从客户端上传文件到服务器.以下代码是我所得到的. TCP ...

  9. 2022-07-11 Python TCP服务器与客户端

    服务器 创建一个服务器代理类TCPServer,其中有init.accept.handle.close函数. 在初始化函数中创建socket对象,绑定主机的地址和端口,并将socket变为一个监听套接 ...

最新文章

  1. 【Netty】从 BIO、NIO 聊到 Netty
  2. python数据分析numpy_Python数据分析之numpy学习
  3. 如何运用UIControl自定义iOS中的控件
  4. Linux常用网络命令总结
  5. python udp数据报
  6. android studio设置Tab为四空格缩进
  7. 建立数据库的原则(怎样建立一个好的数据库)
  8. 正方形矩阵求对角线之和
  9. 【Antlr】Antlr API 简介
  10. 关于微信开发与微信支付更新
  11. 如何基于对话框的project基于改变BCG的
  12. 设计与人工智能设计师
  13. Pycharm 添加自动表头(包含汉化和英文版本路径)
  14. leaflet快速渲染聚合矢量瓦片(附源码下载)
  15. MTK Camera自定义Vendor Tag
  16. 莱赞多店管家分析Lazada印尼站点热卖商品,商家运营更轻松
  17. 第二章 Android内核和驱动程序(转)
  18. 设置 app 不能在模拟器上运行
  19. suse bios版本_如何检查和更新BIOS版本
  20. web2.0带来的狂潮

热门文章

  1. 深圳绿道-观澜段-乡村一号
  2. vue axios 拦截器配置与封装
  3. 抖音服务器升级维护中,抖音服务器维护中是什么意思
  4. python语句print(chr(65))_Python语句print(chr(ord('B')))的执行结果是
  5. 一枚程序猿的MacBook M1详细体验报告
  6. 金蝶K3 SQL报表系列-客户科目余额表(可用于生成客户保证金查询报表等)
  7. python棋盘放米的故事阅读答案_棋盘摆米的故事你得到了什么启发
  8. 【01 DualCam Framework】
  9. ST-PUZZLE-2.0(一个益智游戏)
  10. 计算机加减乘除运算原理