TCP通信:
1. TCP发端:
socket -> connect -> send -> recv -> close
2. TCP收端:
socket -> bind -> listen -> accept -> recv -> send -> close
3. TCP需要用到的函数:
1. connect:
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
功能:发送链接请求
参数:
sockfd:套接字文件描述符
addr:目的地址存放空间首地址
addrlen:IP地址的大小
返回值:
成功返回0
失败返回-1
2. send:
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
功能:发送数据
参数:
sockfd:文件描述符
buf:发送数据空间首地址
flags:属性默认为0
返回值:
成功返回实际发送字节数
失败返回-1
3. recv:
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
功能:接收数据
参数:
sockfd:套接字文件描述符
buf:存放数据空间首地址
len:最大接收数据的长度
flags:属性,默认为0
返回值:
成功返回实际接收字节数
失败返回-1
如果对方退出,返回0
4. listen:
int listen(int sockfd, int backlog);
功能:监听客户端发送的连接请求(该函数不会阻塞)
参数:
sockfd:套接字文件描述符
backlog:允许等待的尚未被处理的三次握手请求的最大个数
返回值:
成功返回0
失败返回-1
5. accept:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
功能:处理等待连接队列中的第一个连接请求,该函数具有阻塞功能(如果没有人发送链接请求,会阻塞等待)
参数:
socket:套接字文件描述符
address:存放IP地址的空间首地址
addrlen:存放IP地址大小空间首地址
返回值:
成功返回一个新的文件描述符
失败返回-1
4. TCP编程练习:
1. 利用TCP实现跨主机的文件发送:
send.c
#include "head.h"
int main(void)
{
FILE *fd = NULL;
int sockfd = 0;
int ret = 0;
struct sockaddr_in severaddr;
ssize_t nsize = 0;
size_t rret = 0;
char filename[100] = {0};
char tmpbuff[1024] = {0};
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1)
{
perror("fail to socket");
return -1;
}
severaddr.sin_family = AF_INET;
severaddr.sin_port = htons(50000);
severaddr.sin_addr.s_addr = inet_addr("192.168.1.162");
ret = connect(sockfd,(struct sockaddr *)&severaddr, sizeof(severaddr));
if(ret == -1)
{
perror("fail to connect");
return -1;
}
scanf("%s", filename);
fd = fopen(filename, "r");
if(fd == NULL)
{
perror("fail to fopen");
return -1;
}
nsize = send(sockfd, filename, strlen(filename), 0);
if(nsize == -1)
{
perror("fail to send");
return -1;
}
while(1)
{
memset(tmpbuff, 0, sizeof(tmpbuff));
rret = fread(tmpbuff, 1, sizeof(tmpbuff), fd);
if(rret == 0)
{
break;
}
usleep(1000);
nsize = send(sockfd, tmpbuff, rret, 0);
if(nsize == -1)
{
perror("fail to send");
return -1;
}
}
fclose(fd);
close(sockfd);
return 0;
}
recv.c
#include "head.h"
int main(void)
{
FILE *fd = NULL;
int ret = 0;
int sockfd = 0;
int contfd = 0;
ssize_t nsize = 0;
char *ptmp = NULL;
char tmpbuff[1024] = {0};
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(50000);
serveraddr.sin_addr.s_addr = INADDR_ANY;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1)
{
perror("fail to socket");
return -1;
}
ret = bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
if(ret == -1)
{
perror("fail to ret");
return -1;
}
ret = listen(sockfd, 10);
if(ret == -1)
{
perror("fail to listen");
return -1;
}
contfd = accept(sockfd, NULL, NULL);
if(contfd == -1)
{
perror("fail to accept");
return -1;
}
nsize = recv(contfd, tmpbuff, sizeof(tmpbuff), 0);
if(nsize == -1)
{
perror("fail to recv");
return -1;
}
fd = fopen(tmpbuff, "w");
if(fd == NULL)
{
perror("fail to fopen");
return -1;
}
while(1)
{
memset(tmpbuff, 0, sizeof(tmpbuff));
nsize = recv(contfd, tmpbuff, sizeof(tmpbuff), 0);
if(nsize <= 0)
{
break;
}
fwrite(tmpbuff, 1, nsize, fd);
}
fclose(fd);
close(contfd);
close(sockfd);
return 0;
}