TCP 仅创建服务器和客户端
cs架构 服务器
1.创建套接字 socket
2.绑定套接字 bind
3.监听套接字listen
4.被动等待连接 accept
5.send/recv read/write(linux)
6.关闭套接字 close
客户端
1.创建套接字 socket
2.绑定 bind(可省略)
3.主动连接 connect
4.send/recv read/write(linux)
5.关闭套接字 close
//1.socket创建套接字
int socket(int domain, int type, int protocol);
/*返回值 成功返回文件描述符,失败返回-1
参数:domain 地址族 ipv4 AF_INET
type 类型 SOCK_STREAM (TCP)
protocpl 协议 一般默认0
*/
eg:
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(ERROR == sockfd)
{
perror("socket");
return ERROR;
}
//2.bind绑定套接字
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
/*
返回值:成功返回0 失败返回-1
参数:sockfd 文件描述符
addr 装有信息的结构体
addrlen 结构体的长度
*/
/*
网络字节序:htons() 把短整型的数据转换位网络字节序
ntohs() 把网络字节序转成短整型的数据
inet_addr()把字符串类型的ip地址转换位网络字节序 “192.168.3.4”
char *inet_ntoa(struct in_addr in);
struct sockaddr_in {
sa_family_t sin_family; address family: AF_INET
in_port_t sin_port; port in network byte order
struct in_addr sin_addr; internet address
};
Internet address.
struct in_addr {
uint32_t s_addr; address in network byte order
};
*/
eg:
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(6666);
addr.sin_addr.s_addr = inet_addr(0.0.0.0);
if(ERROR == bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)))
{
perror("bind");
return ERROR;
}
3./*设置监听队列*/
int listen(int sockfd, int backlog);
/*
返回值 成功返回0, 失败返回-1
参数:sockfd 文件描述符
backlog 监听队列的大小 一般3或者4
*/
eg:
if(ERROR == listen(sockfd, 3))
{
perror("listen");
return -1;
}
/*被动等待连接*/
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
/*
返回值:成功返回客户端的文件描述符,失败返回-1
参数:sockfd 文件描述符
addr 接收客户端信息的内存首地址
addrlen 空间的大小(不能用sizeof,需要先计算出来赋值给一个变量,把变量地址传递进来)
*/
eg:
struct sockaddr_in c_addr;
memset(&c_addr, 0, sizeof(c_addr));
socklen_t c_addrlen = sizeof(c_addr);
int connfd;
flag:
if(ERROR == (connfd = accept(sockfd, (struct sockaddr*)&c_addr, &c_addrlen))) //阻塞等待客户端连接
{
perror("listen");
exit(ERROR);
}
printf("connfd is %d\n", connfd);
printf("port is %d\n", ntohs(c_addr.sin_port));
printf("ip is %s\n", inet_ntoa(c_addr.sin_addr));
/*发送函数*/
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
/*
返回值: 成功返回发送数据的字节数,失败-1
参数:sockfd 文件描述符
buf 发送内容首地址
len 内容长度
flags 0和write一样
*/
eg:
char buf[20] = {0};
ssize_t ret;
ret = recv(connfd, buf, sizeof(buf), 0);
if(ERROR == ret)
{
perror("recv");
exit(ERROR);
}
if(ZERO == ret)
{
goto flag;
}
printf("recv number=%ld\n", ret);
printf("data is %s\n", buf);
/*接收函数(阻塞)*/
ssize_t recv(int sockfd, const void *buf, size_t len, int flags);
/*
返回值: 成功返回读取数据的字节数,失败-1,客户端退出返回0
参数:sockfd 文件描述符
buf 接收内容首地址
len 内容长度
flags 0和read一样
*/
/*客户端主动连接服务器*/
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
/*
返回值 成功返回0, 失败返回-1
参数:sockfd 文件描述符
addr 需要连接的服务器的地址信息
addrlen 结构体长度
*/
fgets(buf, sizeof(buf), stdin);
ret = send(connfd, buf, sizeof(buf), ZERO);
if(ERROR == ret)
{
perror("send");
exit(ERROR);
}
printf("send number=%ld\n", ret);