目录
socket模型创建流程
注:bind()绑定ip+port
listen():设置监听上限,同时建立连接的上限数
accpet():阻塞监听客户端连接
connect():客户端绑定ip+port
socket函数
创建一个套接字
#include <sys/socket.h>
/*
domain: AF_INET、AF_INET6、AF_UNIX
type: SOCK_STREAM(流式协议)、SOCK_DGRAM (报式协议)
protocol:0(流式协议:TCP、报式协议:UDP)
返回值:成功:新套接字所对应文件描述符
失败:-1,error
*/
int socket(int domain,int type,int protocol);
服务器端函数
bind函数
给socket绑定一个地址结构(ip+port)
#include <sys/types.h>
#include <sys/socket.h>
/*
sockfd:socket函数返回值
addr:(struct sockaddr*)&addr sockaddr结构体
addrlen:sizeof(addr)地址结构的大小
返回值:
成功:0
失败:-1 error
*/
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
listen函数
设置同时与服务器建立连接的上限数。(同时进行3次握手的客户端数量)
#include <sys/types.h>
#include <sys/socket.h>
/*
sockfd:socket函数返回值
backlog:上限数值,最大值:128
返回值:
成功:0
失败:-1 error
*/
int listen(int sockfd, int backlog);
accept函数
阻塞等待客户建立连接,成功的话,返回一个与客户端成功连接的socket文件描述符。
#include <sys/types.h>
#include <sys/socket.h>
/*
sockfd:socket函数返回值
addr:传出参数。成功与服务器建立连接的那个客户端的地址结构(ip+port)
socklen_t clit_addr_len = sizeof(addr);
addrlen:传入传出:&clit_addr_len
入:addr的大小。出:客户端addr的实际大小
返回值:
成功:能与服务器进行数据通信的socket对应的文件描述
失败:-1,errno
*/
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
客户端函数
connect函数
使用现有的socket与服务器建立连接
#include <sys/types.h>
#include <sys/socket.h>
/*
sockfd:socket函数返回值
addr:传入参数。服务器的地址结构
socklen_t clit_addr_len = sizeof(addr);
addrlen:服务器地址长度
返回值:
成功:能与服务器进行数据通信的socket对应的文件描述
失败:-1 errno
*/
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
如果不使用bind绑定客户端地址结构,采用“隐式绑定”,系统自动分配ip+port
其他函数
read函数
#include <unistd.h>
/*
fd: 文件描述符(文件名或文件路径)
buf: 要写入文件中数据的内存地址
count: 从 buf 写入文件的数据字节数
*/
ssize_t read(int fd, void *buf, size_t count);
注意:当返回值>0时,实际读到的字节数
=0时,socket中,表示对端关闭。close()
=-1时,
若errno == EINTR 被异常中断,需要重启
若errno == EAGIN 或 EWOULDBLOCK以非阻塞方式读数据,但是没有数据。需要,再次读
若errno == ECONNRESET 说明连接被重置
write函数
#include <unistd.h>
/*
fd: 文件描述符(文件名或文件路径)
buf: 要写入文件中数据的内存地址
count: 从 buf 写入文件的数据字节数
*/
ssize_t write(int fd, const void *buf, size_t count);
C/S模型实现
socket实现server端
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
#define SERV_PORT 9527
void sys_err(const char* str){
perror(str);
exit(1);
}
int main(int argc,char* argv[]) {
int ret;
char buf[BUFSIZ],client_IP[1024];
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);
int lfd = socket(AF_INET, SOCK_STREAM, 0 );
if(lfd == -1){
sys_err("socket error");
}
bind(lfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
listen(lfd,128);
clit_addr_len = sizeof(clit_addr);
int cfd = accept(lfd, (struct sockaddr *)&clit_addr, &clit_addr_len);
printf("client ip:%s port:%d\n",
inet_ntop(AF_INET,&clit_addr.sin_addr.s_addr,client_IP,sizeof(client_IP)),
ntohs(clit_addr.sin_port));
if(cfd == -1){
sys_err("accept error");
}
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);
/*closesocket(sock);*/
return 0;
}
socket实现client端
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#define SERV_PORT 9527
void sys_err(const char *str){
perror(str);
exit(1);
}
int main(int argc,char *argv[]){
int cfd;
int conter = 10;
char buf[BUFSIZ];
struct sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
inet_pton(AF_INET,"127.0.0.1", &serv_addr.sin_addr.s_addr);
serv_addr.sin_port = htons(SERV_PORT);
cfd = socket(AF_INET, SOCK_STREAM, 0);
if(cfd==-1){
sys_err("socket error");
}
int ret = connect(cfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
if(ret != 0){
sys_err("connect error");
}
while(--conter){
write(cfd,"hello",5);
ret = read(cfd,buf,sizeof(buf));
write(STDOUT_FILENO,buf,ret);
}
close(cfd);
return 0;
}