1.linuxä¸ç¨cè¯è¨ç¼åå±åç½è天工å
·
2.linux内核通信核心技术:Netlink源码分析和实例分析
3.ãtcpãå
³äºtcp socketåºç°çâconnection reset by peerâåâbroken pipeâ
4.liux c socketç¼ç¨ï¼å¨mainè¿åååºç° stack smash detected
linuxä¸ç¨cè¯è¨ç¼åå±åç½èå¤©å·¥å ·
/*æå¡å¨*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#define SERVPORT
#define BACKLOG
#define MAX(a,b) ((a)>(b)?(a):(b))
void str_echo(int);
void server()
{
int sockfd,client_fd;
struct sockaddr_in my_addr;
struct sockaddr_in remote_addr;
socklen_t sin_size;
if((sockfd=socket(AF_INET,SOCK_STREAM,0))== -1)
{
perror("socket create error!");
exit(1);
}
my_addr.sin_family=AF_INET;
my_addr.sin_port=htons(SERVPORT);
my_addr.sin_addr.s_addr=INADDR_ANY;
bzero(&(my_addr.sin_zero),8);
if(bind(sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))==-1)
{
perror("bind error!");
exit(1);
}
if(listen(sockfd,BACKLOG)==-1)
{
perror("listen error!");
exit(1);
}
while(1)
{
sin_size=sizeof(struct sockaddr_in);
if((client_fd=accept(sockfd,(struct sockaddr *)&remote_addr,&sin_size))==-1)
{
perror("accept error!");
continue;
}
printf("received a connection from %s\n",inet_ntoa(remote_addr.sin_addr));
if(!fork())
{
close(sockfd);
str_echo(client_fd);
exit(0);
}
close(client_fd);
}
}
void str_echo(int sockfd)
{
int maxfd;
char sendbuf[]={ 0};
char recvbuf[]={ 0};
fd_set rfds;
while(1)
{
FD_SET(0,&rfds);
FD_SET(sockfd,&rfds);
maxfd=MAX(0,sockfd)+1;
select(maxfd,&rfds,NULL,NULL,NULL);
if(FD_ISSET(sockfd,&rfds))
{
bzero(recvbuf,);
recv(sockfd,recvbuf,,0);
printf("C:%s\n",recvbuf);
}
if(FD_ISSET(0,&rfds))
{
read(0,sendbuf,);
send(sockfd,sendbuf,strlen(sendbuf),0);
bzero(sendbuf,);
}
}
}
int main()
{
server();
return 0;
}
/*客æ·ç«¯*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define SERVPORT
#define MAXSIZE
#define MAX(a,b) ((a)>(b)?(a):(b))
void client(int argc,char **argv)
{
int sockfd,maxfd;
char sendbuf[MAXSIZE]={ 0};
char recvbuf[MAXSIZE]={ 0};
// struct hostent *host;
struct sockaddr_in serv_addr;
fd_set rfds;
/* if(argc<2)
{
fprintf(stderr,"Please enter the sserver's name!\n");
exit(1);
}
if((host=gethostbyname(argv[1]))==NULL)
{
herror("get host by name error!\n");
exit(1);
}
*/
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("socket creat error!\n");
exit(1);
}
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(SERVPORT);
// serv_addr.sin_addr=*((struct in_addr *)host->h_addr);
serv_addr.sin_addr.s_addr=inet_addr(".0.0.1");
bzero(&(serv_addr.sin_zero),8);
if(connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(struct sockaddr))==-1)
{
perror("connection error!\n");
exit(1);
}
FD_ZERO(&rfds);
while(1)
{
FD_SET(0,&rfds);
FD_SET(sockfd,&rfds);
maxfd=MAX(0,sockfd)+1;
select(maxfd,&rfds,NULL,NULL,NULL);
if(FD_ISSET(sockfd,&rfds))
{
bzero(recvbuf,MAXSIZE);
recv(sockfd,recvbuf,MAXSIZE,0);
printf("S:%s\n",recvbuf);
}
if(FD_ISSET(0,&rfds))
{
fgets(sendbuf,MAXSIZE,stdin);
send(sockfd,sendbuf,strlen(sendbuf),0);
bzero(sendbuf,MAXSIZE);
}
}
// close(sockfd);
}
int main(int argc,char **argv)
{
client(argc,argv);
return 0;
}
linux内核通信核心技术:Netlink源码分析和实例分析
Linux内核通信核心技术:Netlink源码分析和实例分析
什么是netlink?Linux内核中一个用于解决内核态和用户态交互问题的机制。相比其他方法,netlink提供了更安全高效的交互方式。它广泛应用于多种场景,例如路由、用户态socket协议、MPlayer的源码防火墙、netfilter子系统等。
Netlink内核代码走读:内核代码位于net/netlink/目录下,包括头文件和实现文件。头文件在include目录,提供了辅助函数、宏定义和数据结构,字幕合成源码对理解消息结构非常有帮助。关键文件如af_netlink.c,其中netlink_proto_init函数注册了netlink协议族,使内核支持netlink。
在客户端创建netlink socket时,使用PF_NETLINK表示协议族,unity canvas源码SOCK_RAW表示原始协议包,NETLINK_USER表示自定义协议字段。sock_register函数注册协议到内核中,以便在创建socket时使用。
Netlink用户态和内核交互过程:主要通过socket通信实现,包括server端和client端。Centernet源码讲解netlink操作基于sockaddr_nl协议套接字,nl_family制定协议族,nl_pid表示进程pid,nl_groups用于多播。消息体由nlmsghdr和msghdr组成,用于发送和接收消息。南宫28源码内核创建socket并监听,用户态创建连接并收发信息。
Netlink关键数据结构和函数:sockaddr_nl用于表示地址,nlmsghdr作为消息头部,msghdr用于用户态发送消息。内核函数如netlink_kernel_create用于创建内核socket,netlink_unicast和netlink_broadcast用于单播和多播。
Netlink用户态建立连接和收发信息:提供测试例子代码,代码在github仓库中,可自行测试。核心代码包括接收函数打印接收到的消息。
总结:Netlink是一个强大的内核和用户空间交互方式,适用于主动交互场景,如内核数据审计、安全触发等。早期iptables使用netlink下发配置指令,但在iptables后期代码中,使用了iptc库,核心思路是使用setsockops和copy_from_user。对于配置下发场景,netlink非常实用。
链接:内核通信之Netlink源码分析和实例分析
ãtcpãå ³äºtcp socketåºç°çâconnection reset by peerâåâbroken pipeâ
å¨socketéä¿¡è¿ç¨ä¸ï¼ç»å¸¸åç°å®¢æ·ç«¯æè æå¡å¨çæ¥å¿ä¸åºç°âbroken pipeâæè âconnection reset by peerâçé误æ示ã
以åä¸ç´ä»¥ä¸ºèªå·±ç解äºè¿ä¸¤ä¸ªé误å¼å¸¸æ示æå å«çæä¹ï¼èå®é ç解å®å ¨é误ã
æçé误ç解åä¸é¢è¿æ®µæ¥èªblogspotç表述差ä¸å¤ï¼
```
Maybe I'm just dumb, but I always thought "broken pipe" meant, "the other end of this socket closed before I finished sending something" and "connection reset by peer" meant, well, roughly the same thing. (As well as indicating some slightly more esoteric problems.)
Turns out though, "broken pipe" actually means "I just tried to send something and the socket was already closed to sending."
So in the following example, if the other end of (TCP) socket "sock" closes or dies before the write method, "connection reset by peer" will be raised. The next write will give a broken-pipe error, since the socket now knows that further sending is invalid.
```
```
try:
sock.write('foo')
except:
pass # connection reset by peer
sock.write('bar') # broken pipe
```
RSTçæ å¿ä½ï¼è¿ä¸ªæ è¯ä¸ºå¨å¦ä¸å ç§æ åµä¸ä¼è¢«è®¾ç½®ï¼ä»¥ä¸æ¯æäºè§£çæ åµï¼å¯è½è¿ææ´å¤çåºæ¯ï¼æ²¡æéªè¯ï¼
1. å½å°è¯åæªå¼æ¾çæå¡å¨ç«¯å£å»ºç«tcpè¿æ¥æ¶ï¼æå¡å¨tcpå°ä¼ç´æ¥å客æ·ç«¯åéresetæ¥æ
2. åæ¹ä¹åå·²ç»æ£å¸¸å»ºç«äºéä¿¡ééï¼ä¹å¯è½è¿è¡è¿äºäº¤äºï¼å½æä¸æ¹å¨äº¤äºçè¿ç¨ä¸åçäºå¼å¸¸ï¼å¦å´©æºçï¼å¼å¸¸çä¸æ¹ä¼å对端åéresetæ¥æï¼éç¥å¯¹æ¹å°è¿æ¥å ³é
3. å½æ¶å°TCPæ¥æï¼ä½æ¯åç°è¯¥æ¥æä¸æ¯å·²å»ºç«çTCPè¿æ¥å表å¯å¤ççï¼åå ¶ç´æ¥å对端åéresetæ¥æ
4. ackæ¥æ丢失ï¼å¹¶ä¸è¶ åºä¸å®çéä¼ æ¬¡æ°ææ¶é´åï¼ä¼ä¸»å¨å对端åéresetæ¥æéæ¾è¯¥TCPè¿æ¥
å ¶å®æ们javaå¼å¸¸éçå°çBroken pipeæè Connection reset by peerä¿¡æ¯ä¸æ¯jdkæè jvméå®ä¹çï¼æçå°è¿äºå ³é®åå¾å¾ä¼é¦å æç´¢ä¸jdkæè hotspotæºç æ¾å°ä½ç½®è¿è¡ä¸ä¸æåæï¼ä½æ¯æ²¡æ¾å°ï¼åé¢ææ³å°åºè¯¥æ¯Linuxæè glibcéå®ä¹çï¼æç¶å¨glibcéçå°äºå¦ä¸çæè¿°åå®ä¹ã
对äºBroken pipeå¨ç®¡éçå¦å¤ä¸ç«¯æ²¡æè¿ç¨å¨è¯»çæ¶åå°±ä¼æåºæ¤å¼å¸¸ï¼Connection reset by peerçæè¿°å ¶å®ä¸æ¯å¾æ£ç¡®ï¼ä»æçå®è·µæ¥çåªæè¿°äºä¸æ¹é¢ï¼å ¶å®å¨æä¸ç«¯æ£å¸¸closeä¹åï¼ä¹æ¯å¯è½ä¼ææ¤å¼å¸¸çã
connection reset by peerâåâbroken pipeâåºç°çåºæ¯ï¼
1ï¼å¾ä¸ä¸ªå¯¹ç«¯å·²ç»closeçééåæ°æ®çæ¶åï¼å¯¹æ¹çtcpä¼æ¶å°è¿ä¸ªæ¥æï¼å¹¶ä¸åé¦ä¸ä¸ªresetæ¥æãå½æ¶å°resetæ¥æçæ¶åï¼ç»§ç»åselect读æ°æ®çæ¶åå°±ä¼æåºConnect reset by peerçå¼å¸¸ï¼ã
2ï¼å½ç¬¬ä¸æ¬¡å¾ä¸ä¸ªå¯¹ç«¯å·²ç»closeçééåæ°æ®çæ¶åä¼åä¸é¢çæ åµä¸æ ·ï¼ä¼æ¶å°resetæ¥æãå½å次å¾è¿ä¸ªsocketåæ°æ®çæ¶åï¼å°±ä¼æåºBroken pipeäº ãæ ¹æ®tcpç约å®ï¼å½æ¶å°resetå çæ¶åï¼ä¸å±å¿ é¡»è¦ååºå¤çï¼è°ç¨å°socketæ件æ述符è¿è¡å ³éï¼å ¶å®ä¹æå³çpipeä¼å ³éï¼å æ¤ä¼æåºè¿ä¸ªé¡¾åæä¹çå¼å¸¸ã
ä»tcpåçè§åº¦ç解Broken pipeåConnection Reset by Peerçåºå«
/blog////tcp-broken-pipe
å ³äºtcp socketåºç°çâconnection reset by peerâåâbroken pipeâ
////%E5%%B3%E4%BA%8Etcp-socket%E5%%BA%E7%8E%B0%E7%9A%connection-reset-by-peer%E5%%8Cbroken-pipe
liux c socketç¼ç¨ï¼å¨mainè¿åååºç° stack smash detected
å¦ææ¶å°ä¸ªå符
é£ä¹ recvbuff[recvbytes] = '\0';
è¿å¥å°±åè¶çäº
åºè¯¥æ¹ä¸º
<code>
// MAXSIZE æ¹ä¸º MAXSIZE -1
if((recvbytes=recv(sockfd,recvbuff,MAXSIZE-1,0))==-1)
{
perror("recv æ¥åæ°æ®åºé");
exit(2);
}
</code>