客户端-服务器模型
客户端和服务器都得创建一个套接字--一对套接字
C/S一共有3个套接字 一个监听 两个通信
socket函数
#include <sys/socket.h>
socket
int socket(int domain, int type, int protocol); 创建一个套接字
domain: AF_INET AF_INET6
tape:协议类型,SOCK_STREAM,SOCK_DGRAM(流式协议,报式协议)
protocol:0
返回值:成功,返回新套接字对应的文件描述符
失败:-1 err
bind
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
给socket绑定一个ip+端口号,称为地址结构
sockfd:socket函数的返回值
addr:要初始化,传入参数
addr:(struct sockaddr*)&addr
addrlen:sizeof(addr) 地址结构的大小
返回值:
成功:0
失败:-1
listen
int listen(int sockfd, int backlog);
设置同时与服务器建立连接的上线数(同时进行3次握手的客户端数量)
sockfd:socket函数返回值
backlog:上限数值,最大128
返回值:
成功:0
失败:-1
accept
int accept(int sockfd, struct sockaddr *_Nullable restrict addr,
socklen_t *_Nullable restrict addrlen);
阻塞等待客户端建立连接,成功,返回一个与客户端成功连接的socket文件描述符
sockfd:socket函数返回值
addr:传出参数,传出成功与服务器建立连接的客户端的地质结构
socklen_t clit_addr_len =sizeof(addr);
addrlen:地址结构长度,传入传出,&clit_addr_len
传入时为addr的大小,
出:客户端addr的实际大小
返回值:
成功 返回能与服务器进行数据通信的socket文件描述符
失败:-1
connect
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
使用现有的socket与服务器建立连接
sockfd:socket函数返回值
addr:传入参数,服务器的地址结构,
addrlen:服务器地址结构的长度
返回值:
成功:0
失败:-1
如果不使用bind绑定客户端地址结构,采用隐式绑定,系统自动分配
TCP通信流程分析:
转换大小写
server:
socket() 创建套接字
bind() 绑定服务器地址结构
listen() 设置监听上限
accept() 阻塞监听客户端连接
read(fd) 读socket获取客户端数据
小写-》大写 toupper()
write(fd)
close()
client:
socket()
connect() 与服务器建立连接
write() 写数据
read() 读转换后的数据
显示读取结果
close()
#include<stdio.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<pthread.h>
#include<netinet/in.h>
#include<sys/types.h>
#include <ctype.h>
#include <unistd.h>
#define SERV_PORT 9527void sys_err(const char *str){
perror(str);
exit(1);
}int main(int argc,char *argv[]){
int lfd=0,cfd=0;
int ret;
char buf[BUFSIZ];struct sockaddr_in serv_addr,clit_addr;
socklen_t clit_addr_len;serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(SERV_PORT);
serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);// server:
// socket() 创建套接字
lfd = socket(AF_INET,SOCK_STREAM,0);
if (lfd==-1)
{
sys_err("socket error");
}// bind() 绑定服务器地址结构
bind(lfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
// listen() 设置监听上限listen(lfd,128);
// accept() 阻塞监听客户端连接
//
clit_addr_len=sizeof(clit_addr);
cfd = accept(lfd,(struct sockaddr*)&clit_addr,&clit_addr_len);
if (cfd==-1)
{
sys_err("accept err");
}
// read(fd) 读socket获取客户端数据
while (1)
{
ret = read(cfd,buf,sizeof(buf));
write(STDOUT_FILENO,buf,ret);for (int i = 0; i < ret; i++)
{
buf[i]=toupper(buf[i]);
}write(cfd,buf,ret);
}
close(lfd);
close(cfd);return 0;
}
// 小写-》大写 toupper()// write(fd)
// close()
// client:
// socket()
// connect() 与服务器建立连接
// write() 写数据
// read() 读转换后的数据
// 显示读取结果
// close()