TCP/IP的TCP socket通信过程
2017-12-27 20:36
525 查看
传统的TCP/IP通信过程依赖于socket,位于应用层和传输层之间,使得应用程序可以进行通信。相当于港口城市的码头,使得城市之间可以进行货物流通。服务器和客户端各有不同的通信流程。
调用socket(),分配文件描述符,即监听套接字
调用bind(),将套接字与本地IP地址和端口绑定
调用listen(),监听特定端口,socket()创建的套接字是主动的,调用listen使得该文件描述符为监听套接字,变主动为被动
调用accept(),阻塞等待客户端连接
2、数据交互阶段
调用read(),阻塞等待客户端发送的请求,收到请求后从read()返回,处理客户端请求
调用write(),将处理结果发送给客户端,然后继续调用read()等待客户端请求
3、关闭连接
当read()返回0的时候,说明客户端发来了FIN数据包,即关闭连接,也会调用close()关闭连接套接字和监听套接字
调用socket(),分配文件描述符
调用connect(),向服务器发送建立连接请求
2、数据交互阶段
调用write(),将请求发送给服务器
调用read(),阻塞等待服务器应答
3、关闭连接
当没有数据发送的时候,调用close()关闭连接套接字,即关闭连接,向服务器发送FIN数据报
四、C语言代码
服务器端
/* File name: server.c*/
//服务器端
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#define MAXLINE 4096
#define PORT 8000
int main(void){
//定义服务器监听套接字和连接套接字
int listen_fd = -1, connect_fd = -1;//初始化为-1
struct sockaddr_in servaddr;//定义服务器对应的套接字地址
//服务器接收和发送缓冲区
char sendbuf[MAXLINE], recbuf[MAXLINE];
//初始化套接字地址结构体
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;//IPv4
servaddr.sin_port = htons(PORT);//设置监听端口
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//表示接收任意IP的连接请求
//创建套接字
if((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
//如果创建套接字失败,返回错误信息
//strerror(int errnum)获取错误的描述字符串
printf("create socket error: %s(error: %d)\n", strerror(errno), errno);
exit(0);
}
//绑定套接字和本地IP地址和端口
if(bind(listen_fd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){
//绑定出现错误
printf("bind socket error: %s(error: %d)\n", strerror(errno), errno);
exit(0);
}
//使得listen_fd变成监听描述符
if(listen(listen_fd, 10) == -1){
printf("listen socket error: %s(error: %d)\n", strerror(errno), errno);
exit(0);
}
//accept阻塞等待客户端请求
printf("等待客户端发起连接\n");
while(1){
if((connect_fd = accept(listen_fd, (struct sockaddr*)NULL, NULL)) == -1){
printf("accept socket error: %s(error: %d)\n", strerror(errno), errno);
continue;
}
//可以一直保持连接
while(1){
//读取客户端发来的信息
ssize_t len = read(connect_fd, recbuf, sizeof(recbuf));
if(len < 0){
if(errno == EINTR){
continue;
}
exit(0);
}
printf("接收客户端的请求:%s\n", recbuf);
//向客户端发送信息
printf("回复客户端信息:");
fgets(sendbuf, sizeof(sendbuf), stdin);
write(connect_fd, sendbuf, sizeof(sendbuf));
}
//关闭连接套接字
close(connect_fd);
}
//关闭监听套接字
close(listen_fd);
}
客户端
一、服务器
1、建立连接阶段调用socket(),分配文件描述符,即监听套接字
调用bind(),将套接字与本地IP地址和端口绑定
调用listen(),监听特定端口,socket()创建的套接字是主动的,调用listen使得该文件描述符为监听套接字,变主动为被动
调用accept(),阻塞等待客户端连接
2、数据交互阶段
调用read(),阻塞等待客户端发送的请求,收到请求后从read()返回,处理客户端请求
调用write(),将处理结果发送给客户端,然后继续调用read()等待客户端请求
3、关闭连接
当read()返回0的时候,说明客户端发来了FIN数据包,即关闭连接,也会调用close()关闭连接套接字和监听套接字
二、客户端
1、建立连接阶段调用socket(),分配文件描述符
调用connect(),向服务器发送建立连接请求
2、数据交互阶段
调用write(),将请求发送给服务器
调用read(),阻塞等待服务器应答
3、关闭连接
当没有数据发送的时候,调用close()关闭连接套接字,即关闭连接,向服务器发送FIN数据报
三、TCP通信过程
四、C语言代码
服务器端/* File name: server.c*/
//服务器端
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#define MAXLINE 4096
#define PORT 8000
int main(void){
//定义服务器监听套接字和连接套接字
int listen_fd = -1, connect_fd = -1;//初始化为-1
struct sockaddr_in servaddr;//定义服务器对应的套接字地址
//服务器接收和发送缓冲区
char sendbuf[MAXLINE], recbuf[MAXLINE];
//初始化套接字地址结构体
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;//IPv4
servaddr.sin_port = htons(PORT);//设置监听端口
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//表示接收任意IP的连接请求
//创建套接字
if((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
//如果创建套接字失败,返回错误信息
//strerror(int errnum)获取错误的描述字符串
printf("create socket error: %s(error: %d)\n", strerror(errno), errno);
exit(0);
}
//绑定套接字和本地IP地址和端口
if(bind(listen_fd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){
//绑定出现错误
printf("bind socket error: %s(error: %d)\n", strerror(errno), errno);
exit(0);
}
//使得listen_fd变成监听描述符
if(listen(listen_fd, 10) == -1){
printf("listen socket error: %s(error: %d)\n", strerror(errno), errno);
exit(0);
}
//accept阻塞等待客户端请求
printf("等待客户端发起连接\n");
while(1){
if((connect_fd = accept(listen_fd, (struct sockaddr*)NULL, NULL)) == -1){
printf("accept socket error: %s(error: %d)\n", strerror(errno), errno);
continue;
}
//可以一直保持连接
while(1){
//读取客户端发来的信息
ssize_t len = read(connect_fd, recbuf, sizeof(recbuf));
if(len < 0){
if(errno == EINTR){
continue;
}
exit(0);
}
printf("接收客户端的请求:%s\n", recbuf);
//向客户端发送信息
printf("回复客户端信息:");
fgets(sendbuf, sizeof(sendbuf), stdin);
write(connect_fd, sendbuf, sizeof(sendbuf));
}
//关闭连接套接字
close(connect_fd);
}
//关闭监听套接字
close(listen_fd);
}
客户端
/* File name: client.c */ //客户端 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> #include<unistd.h> #include<sys/types.h> #include<sys/socket.h> #include<arpa/inet.h> #define MAXLINE 4096 #define PORT 8000 int main(void){ //定义客户端套接字 int sockfd = -1; //定义想连接的服务器的套接字地址 struct sockaddr_in servaddr; //发送和接收数据的缓冲区 char sendbuf[MAXLINE], recbuf[MAXLINE]; //初始化服务器套接字地址 memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET;//IPv4 servaddr.sin_port = htons(PORT);//想连接的服务器的端口 servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");//服务器的IP地址 //创建套接字 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){ printf("create socket error: %s(error: %d)\n", strerror(errno), errno); exit(0); } //向服务器发送连接请求 if(connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){ //连接失败 printf("connect socket error: %s(error: %d)\n", strerror(errno), errno); exit(0); } while(1){ //向服务器发送信息 printf("向服务器发送信息:"); fgets(sendbuf, sizeof(sendbuf), stdin); write(sockfd, sendbuf, sizeof(sendbuf)); //从服务器接收信息 ssize_t len = read(sockfd, recbuf, sizeof(recbuf)); if(len < 0){ if(errno == EINTR){ continue; } exit(0); } printf("服务器回应:%s\n", recbuf); } //关闭套接字 close(sockfd); }
相关文章推荐
- Socket通信中的多进程编程(TCP/IP通信过程)
- Python网络通信之socket模块(四)基于Tcp/Ip的TCP交互通信serve/client的编写过程
- TCP/IP基础概念及通信过程举例
- tcp ip 通信socket
- Linux socket编程入门及客户端服务器端通信实现 – 提高篇:TCP连接过程分析
- 网络层、传输层、应用层、端口通信协议编程接口 - http,socket,tcp/ip 网络传输与通讯知识总结
- Java 网络编程(五) 使用TCP/IP的套接字(Socket)进行通信
- 利用TCP/IP模型理解数据通信过程
- Java网络编程笔记(四):点对面通信(Socket基于TCP/IP)协议
- Android Socket(TCP/IP) 通信
- socket通信之一:TCP/IP模型与socket
- 对Socket通信、TCP/IP和Http的理解
- 基于TCP的socket通信过程及例子
- Android Socket(TCP/IP) 通信
- Python socket网络编程TCP/IP服务器与客户端通信
- 【Java TCP/IP Socket】基于NIO的TCP通信(含代码)
- TCP/IP通信过程(以发送电子邮件为例)
- (四十五)网络基础——OSI七层模型简介和TCP/IP四层模型及其通信过程
- Java 网络编程(五) 使用TCP/IP的套接字(Socket)进行通信
- 网络通信——socket(TCP/IP).Http,同步和异步的区别