linux
最近一直再看gstreamer,使用了很多插件和库,虽然我总结了一部分rtsp流程,对于这么大的框架,明显感觉分析不了,比如linux API、Gobject(Glib库)推荐一本入门书籍《linux下c编程》,有案例可以debug
socket
socket 是网络编程一个最基本的函数,本地应用,远端应用都可以用来通信,基于 tcp 和 udp 传输
socket 通信模型
服务器端
第一步:创建socket (与网络连接的套接口),返回一个文件描述符,socket 物理上表现为网络连接,编程上表现为文件描述符。
第二步: bind 绑定 创建socket和本机的IP地址和端口号
第三步: 调用listen 指定socket为被动套接口,监听网络到达的请求
第四步: 调用accept使得socket可以接收网络请求,如果没有连接请求,socket 进入 阻塞状态,,反之返回一个连接套接口socket (此时TCP三次握手已经完成)
第五步: read 读取数据
第六步: 处理请求,根据请求使用write发送数据
第七步: 最后调用close 关闭连接套接口
客户端
第一步: 创建一个socket
第二步: 调用connect 传入参数服务器的 IP PORT 发起连接,当三次握手完成后,connect 会返回
第三步: write 向socket 写入数据,发送请求
第四步: 当服务器返回数据,使用read 读取数据内容
第五步: 最后通过close 关闭socket
函数说明
想使用socket 必须包含 头文件
#include <sys/types.h>
#include <sys/socket.h>
函数原型:socket
int socket(int family, int type, int protocol);
/*
return 返回文件描述符 fd
family 协议族 地址族 AF_INET 表示ipv4
type 的服务类型 TCP对应SOCK_STREAM 表示流 UDP对应 SOCK_DGRAM 表示数据报
protocol用0表示默认family 和 type
*/
函数原型:bind
int bind(int sockfd,const struct sockaddr * localaddr,socklen_t addrlen);
/*
return 成功返回0 反之-1
sockfd socket 创建的套接字描述符
localaddr 指定本地的IP地址和端口
addrlen 地址结构的字节数大小
*/
函数原型:listen
int listen(int sockfd,int queuelen);
/*
return 成功返回0 反之-1
sockfd socket创建的套接口
queuelen 请求对的大小
*/
函数原型:accept
int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);
/*
return 返回套接字描述符
sockfd socket 创建的套接字描述符
addr 地址结构的指针 accept 后,包含远程的IP地址和协议端口号
addrlen addr结构大小的存放地址,调用结束后获取远程的socket实际地址大小
*/
函数原型: connect
int connect(int sockfd,const struct sockaddr *addr,socklen_t addrlen);
/*
return 成功返回0 反之-1
sockfd 套接字的描述符
addr 远程机器端点的地址
addrlen 是struct sockaddr 结构体的大小
*/
函数原型:send
int send( SOCKET sockfd,char *buf,int len,int flags );
/*
sockfd: 接收端套接字描述符
buf: 用来存放send函数的数据的缓冲区
len: 指明buff的长度
flags: 一般置为0
*/
函数原型:recv
int recv( SOCKET sockfd, char *buf, int len, int flags);
/*
sockfd: 接收端套接字描述符
buf: 用来存放recv函数接收到的数据的缓冲区
len: 指明buff的长度
flags: 一般置为0
*/
struct sockaddr{
unsigned short sa_family;//address family AF_XXX 占用2个字节
char sa_data[14]; //14bytes of protocol address 占用 14个字节
}
//一般不用上面的数据结构,而是使用等价的数据结构
//#include<netinet/in.h>
struct sockaddr_in{
short int sin_family; //address family 占2个字节
unsigned short int sin_port; //port number 占2个字节
struct in_addr sin_addr; //internet address 占用4个字节
unsigned char sin_zero[8]; //same size as struct sockaddr 占8个字节
}
struct in_addr {
in_addr_t s_addr; //占用4个字节
};
demo
环境:ubuntu 16.04 gcc 编译
服务器端实现接收客户端数据,并且对消息处理获取有多少个‘y’,把结果返回给客户端
客户端实现,发送一段字符串消息,接收客户端返回的消息
server.c
这里显示无注释版本,注释版本
int main(int argc, char const *argv[]) {
struct sockaddr_in server_in, client_in;
int sockfd,client_sockfd;
if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1) {
perror("create socket...");
exit(1);
}else{
printf("create socket success ...\n");
}
bzero(&server_in,sizeof(server_in));
server_in.sin_family = AF_INET;
server_in.sin_addr.s_addr = INADDR_ANY;
server_in.sin_port = htons(port);
if ((bind(sockfd,(struct sockaddr *)&server_in,sizeof(server_in)))==-1) {
perror("call bind");
exit(2);
}else{
printf("bind local socket IP address and port ...\n");
}
if ((listen(sockfd,100) ) == -1) {
perror("call listen");
exit(3);
}else{
printf("listen socket ...\n");
}
printf("accepting connections ...\n");
while (1) {
int client_addrlen = sizeof(client_in);
if ((client_sockfd = accept(sockfd,(struct sockaddr *)&client_in,&client_addrlen))==-1) {
perror("call accept get client ip and port");
exit(4);
} else {
printf("accept client request...\n");
}
if ((recv(client_sockfd,recvbuf,sizeof(recvbuf),0))==-1) {
perror("recv buf message");
exit(5);
} else {
printf("receive buffer...\n");
}
inet_ntop(AF_INET,&client_in.sin_addr,host_name,sizeof(host_name));
printf("received from client (%s):%s\n",host_name,recvbuf);
int sum = 0;
for (int i = 0; i < sizeof(recvbuf); i++) {
if(recvbuf[i] == 'y'){
sum++;
}
}
char* sumstr = (char *)malloc(sizeof(int) + 1);
memset(sumstr, 0, sizeof(int) + 1);
sprintf(sumstr, "%d", sum);
printf("sum = %d sumstr = %s\n",sum,sumstr);
strcpy(sendbuf,"i get your message has ");
strcat(sendbuf,sumstr);
free(sumstr);
strcat(sendbuf," y");
printf("sendbuf: %s\n",sendbuf);
if ((send(client_sockfd,sendbuf,sizeof(sendbuf),0))==-1) {
perror("send buf message");
exit(6);
} else {
printf("send buffer...\n");
}
printf("close connections...\n");
}
close(client_sockfd);
return 0;
}
log:
create socket success …
bind local socket IP address and port …
listen socket …
accepting connections …
accept client request…
receive buffer…
received from client (127.0.0.1):asdsaddyyddddddyydasafdyygfdavas
sum = 6 sumstr = 6
sendbuf: i get your message has 6 y
send buffer…
close connections…
client.c
这里显示无注释版本,注释版本
int main(int argc, char *argv[]) {
int serversockfd,client_sockfd;
struct sockaddr_in client_in,server_in;
char * str = "asdsaddyyddddddyydasafdyygfdavas";
if (argc<2) {
printf("we send default test\n");
printf("Usage: client any_string ip_address \n" );
} else {
str = argv[2];
hostname = argv[1];
}
if ((client_sockfd = socket(AF_INET,SOCK_STREAM,0))==-1) {
perror("create client socket");
exit(1);
}else{
printf("create client socket...\n");
}
bzero(&server_in,sizeof(server_in));
server_in.sin_family = AF_INET;
server_in.sin_port = htons(port);
inet_pton(AF_INET,hostname,&server_in.sin_addr);//将hostname 转化为 网络字节
if ((connect(client_sockfd,(struct sockaddr *)&server_in,sizeof(server_in)))==-1) {
perror("start connect to server...");
exit(2);
} else {
printf("start connect to server...\n");
}
strcpy(sendbuf,str);
printf("start to send message %s to server\n",sendbuf);
if (write(client_sockfd,sendbuf,sizeof(sendbuf))==-1) {
perror("start send message to server...");
exit(3);
} else {
printf("start send message to server..\n");
}
printf("..send message .....wait for response...\n");
if (read(client_sockfd,recvbuf,sizeof(recvbuf))==-1) {
perror(" response from server\n ");
exit(4);
} else {
printf("\n response from server:\n %s\n ",recvbuf);
}
close(client_sockfd);
printf("close connections...\n");
return 0;
}
log:
we send default test
Usage: client any_string ip_address
create client socket…
start connect to server…
start to send message asdsaddyyddddddyydasafdyygfdavas to server
start send message to server..
..send message …..wait for response…response from server:
i get your message has 6 y
close connections…
上面就是一个简单的socket 连接,自己动手写一写能学习到很多东西