TCP服务端
socket()
|
v
bind()
|
v
listen()
|
v
TCP客户端 accept()
socket() |
| v
v 建立连接 阻塞直到有客户端链接
connect()<----->|
| v
+------>write()------->read()/recv()<---+
| | 数据请求 | |
| | | |
| v V处理请求 |
+-------read()<---------write()---------+
| 回应数据 |
v v
close()-------->read()
结束链接 |
v
close()
TCP特点:
1,有链接,提供可靠服务
2,有应答
3,超时重传
4,拥塞控制
5,数据与数据之间没有边界,这但与UDP差异很大
6,存在黏包问题,发的数据包没有边界,接收方无法解析(解决方法:1.固定大小,结构体 2.添加结束标志:譬如\0,可以双方约定)
7,TCP是一个面向连接的传输层协议。通讯过程中链路一直保持。
8,TCP是全双工通信模式,因为收发两端都设有缓存区
9,TCP面向字节流。
TCP小栗子:
--javascripttypescriptbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
服务端:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <time.h>
typedef struct sockaddr* (SA);
int main()
{
int lisfd = socket(AF_INET,SOCK_STREAM,0);
if(lisfd == -1)
{
perror("socket fail");
return -1;
}
struct sockaddr_in ser,cli;
bzero(&cli,sizeof(cli));
bzero(&ser,sizeof(ser));
ser.sin_family = AF_INET;
ser.sin_addr.s_addr = INADDR_ANY;
ser.sin_port = htons(60000);
int ret_bind = bind(lisfd,(SA)&ser,sizeof(ser));
if(ret_bind == -1)
{
perror("bind fail");
return -1;
}
listen(lisfd,3);
socklen_t len = sizeof(cli);
//通信套接字:
int conn = accept(lisfd,(SA)&cli,&len);
if(conn == -1)
{
perror("accept fail");
return -1;
}
//int i = 0;
while(1)
{
char buf[1024] = {0};
bzero(&buf,sizeof(buf));
size_t ret = recv(conn,buf,sizeof(buf),0);
if(ret<=0)
{
break;
}
//sprintf(buf,"%s %s",buf,tm);
timer_t tm;
time(&tm);
sprintf(buf,"%s->%s",buf,ctime(&tm));
//i++;
send(conn,buf,sizeof(buf),0);
}
close(lisfd);
close(conn);
return 0;
}
客服端:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
typedef struct sockaddr * (SA);
int main()
{
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd == -1)
{
perror("socket fail");
return -1;
}
struct sockaddr_in ser,cli;
bzero(&cli,sizeof(cli));
bzero(&ser,sizeof(ser));
ser.sin_addr.s_addr = INADDR_ANY;
ser.sin_family = AF_INET;
ser.sin_port = htons(60000);
int ret = connect(sockfd,(SA)&ser,sizeof(ser));
if(ret == -1)
{
perror("connect fail");
return -1;
}
int i = 10;
while(i--)
{
char buf[1024] = "hello! ";
send(sockfd,buf,sizeof(buf),0);
recv(sockfd,buf,sizeof(buf),0);
printf("%s\n",buf);
fflush(stdout);
sleep(1);
}
close(sockfd);
// printf();
return 0;
}