网络编程——TCP(1)
来源:互联网 发布:oracle 清除表数据 编辑:程序博客网 时间:2024/06/15 22:48
本篇博客将会实现TCP的编程流程,在实现TCP编程之前,先将TCP/IP的四层协议做以简单的介绍。
一、TCP/IP四层协议
TCP/IP的四层协议自底向上分别是数据链路层,网络层,运输层,应用层。很多人也有了解过OSI七层协议,同样的,自底向上分别是物理层,数据链路层,网络层,运输层,会话层,表示层,应用层。而我们主要来说一下TCP/IP四层协议。
1、数据链路层
a.数据链路层实现了网卡接口的网络驱动程序,以处理数据在物理媒介上的传输。
b.常用协议:ARP协议、RARP协议。
2、网络层
a.网络层实现数据包的选路和转发。
b.常用协议:IP协议、ICMP协议。
3、运输层
a.运输层为两台主机实现了端到端的服务。
b.常用协议:TCP协议、UDP协议、SCTP协议。
4、应用层
a.应用层负责处理应用程序的逻辑。
b.常用协议:DNS协议(当然应用层不止这一个协议,这里只说这一个)
二、使用TCP协议完成网络编程
1、完成网络编程需要客户端和服务器端,简单说一下客户端和服务器端。
客户端:请求服务
服务器端:提供服务
2、协议选择(本篇博客选择TCP,之后专门更一篇UDP的)
TCP协议:它是一种面向连接的,可靠的,流式服务。
UDP协议:它是一种无连接,不可靠的,数据报服务。
3、TCP的编程流程:
ser(服务器端):socket、bind、listen、accept、recv/send、close
cli(客户端):socket、(bind)、connect、recv/send、close
接下来说一下用到的函数
a. int socket( int domain, int type, int protocol);
domain:告诉系统选择哪个底层协议族, AF_INET是PF_INET协议族所对应的地址族.
type:选择协议 SOCK_STREAM(TCP), SOCK_UGRAM(UDP).
protocol:这个值一般我们都把它设置为0,表示使用默认协议。本来这个参数是在前两个参数的基础上,再选择一个具体的协议,但是前两个参数已经完全决定了它的值,所以这个参数一般置为0.
b. int bind(int sockfd, const struct sockaddr* addr, int addrlen )
addr:指定IP地址和端口号.
addrlen:指定IP地址和端口号的长度.
c. int listen(int sockfd, int backlog)
backlog:内核监听队列的最大长度,典型参数值是5.
d. int accept(int sockfd, struct sockaddr * addr, int addrlen)
addr:记录客户端的 IP 地址和端口号
addrlen:记录的客户端的 IP 地址和端口号的长度.
注意:bind和accept的addr不是同一个。
e. int connect(int sockfd, struct sockaddr* addr, int addrlen);
addr: 要连接的服务器的 IP 地址和端口号.
addrlen:要连接的服务器的 IP 地址和端口号的长度.
f. revc/send
revc(int sockfd, void *buf, int len, int flags);//读数据
send(int sockfd, const void *buf, int len, int flags);//写数据
buf:指定读/写缓冲区位置
len:指定读/写缓冲区大小
flags:置为0即可
接下来就是代码了
ser.c
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<assert.h>#include<unistd.h>#include<sys/types.h>#include<sys/socket.h>#include<arpa/inet.h>void main(){ int sockfd=socket(AF_INET,SOCK_STREAM,0); assert(sockfd!=-1); struct sockaddr_in ser,cli; ser.sin_family=AF_INET; ser.sin_port=htons(6000); ser.sin_addr.s_addr=inet_addr("127.0.0.1"); int res =bind(sockfd,(struct sockaddr *)&ser,sizeof(ser)); assert(res!=-1); listen(sockfd,5); while(1) { int len=sizeof(cli); int c=accept(sockfd,(struct sockaddr*)&cli,&len); assert(c!=-1); char buff[128]={0}; recv(c,buff,127,0); printf("recv::%s\n",buff); send(c,"I know",strlen("I know"),0); close(c); } close(sockfd);}
cli.c
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<assert.h>#include<unistd.h>#include<sys/types.h>#include<sys/socket.h>#include<arpa/inet.h>void main(){ int sockfd=socket(AF_INET,SOCK_STREAM,0); assert(sockfd!=-1); struct sockaddr_in ser,cli; ser.sin_family=AF_INET; ser.sin_port=htons(6000); ser.sin_addr.s_addr=inet_addr("127.0.0.1"); int res=connect(sockfd,(struct sockaddr*)&ser,sizeof(ser)); assert(res!=-1); send(sockfd,"hello world",strlen("hello world"),0); char buff[128]={0}; recv(sockfd,buff,127,0); printf("recv::%s\n",buff); close(sockfd);}
运行结果
注意:应该先运行服务器端,再运行客户端,当服务器在运行的时候,它会等待客户端给他发送请求,然后响应客服端的请求。要是先运行客户端,再运行服务器端,此时的服务器端是接收不到客户端的请求的,有兴趣的可以试一下,我自己在这上面踩得坑不少。
- 网络编程—TCP
- 网络编程——TCP(1)
- java网络编程—TCP(1)
- 网络编程(1)—TCP
- QT网络编程—TCP
- Linux 网络编程——TCP编程
- PYthon -网络编程—TCP编程
- Qt网络编程———TCP(1)
- 网络编程————TCP
- Linux 网络编程——TCP
- linux网络编程——TCP文件服务器
- Linux 网络编程——TCP
- Java网络编程——TCP介绍
- 黑马程序员——网络编程TCP
- 网络编程——TCP连接
- linux网络编程——初探TCP
- Linux 网络编程——TCP(转)
- python网络编程——TCP
- Add bricks in the wall UVA
- Arduino制作万智牌生命计数器
- C#中使用命名管道通信失败
- (翻译)如何避免对用户体验设计过程产生倦怠(How to Avoid UX Burnout)
- C#使用GDI+绘制直角坐标系
- 网络编程——TCP(1)
- 电脑磁盘逻辑分区不见了
- DrawTools绘图程序代码分析
- SqlServer数据库恢复出错
- Android中的多种对话框样式详解
- “已禁用分布式事务管理器的网络访问”的解决方法
- jq的DOM操作增删改
- 20171109
- recyclerview适配器