服务端建立tco监听的代码如下:
struct sockaddr_in locaddr;
struct socket *sock;
struct socket *newsock;
int rc;
int backlog = 0;
int shutdown;
char *server_ip = "192.168.0.1";
__u32 local_ip = (__u32)inet_addr(server_ip);
int local_port = 1123456
/*第1步:创建套接字*/
rc = sock_create (PF_INET, SOCK_STREAM, 0, &sock);
if (local_ip != 0 || local_port != 0)
{
memset(&locaddr, 0, sizeof(locaddr));
locaddr.sin_family = AF_INET;
locaddr.sin_port = htons(local_port);
locaddr.sin_addr.s_addr = (local_ip == 0) ?
INADDR_ANY : htonl(local_ip);
/*第2步:绑定ip或端口*/
rc = sock->ops->bind(sock, (struct sockaddr *)&locaddr,
sizeof(locaddr));
if (rc == -EADDRINUSE)
{
printk( "Port %d already in use\n", local_port);
}
if (rc != 0)
{
printk( "Error trying to bind to port %d: %d\n", local_port, rc);
}
}
/*第3步:开始监听*/
rc = (*sockp)->ops->listen(*sockp, backlog);
shutdown = rc
/*第4步:进入循环,等待客户端连接,并且可以由全局变量shutdown控制停止服务*/
while (!shutdown) {
wait_queue_t wait;
struct socket *newsock;
struct sockaddr_in sin;
init_waitqueue_entry(&wait, current);
__u32 peer_ip;
int peer_port;
/*内核态套接字编程这一步很重要,在服务端是要建立客户端的socket结构*/
rc = sock_create_lite(PF_PACKET, sock->type, IPPROTO_TCP, &newsock);
if (rc) {
printk("Can't allocate socket\n");
return rc;
}
newsock->ops = sock->ops;
set_current_state(TASK_INTERRUPTIBLE);/*睡眠,等待收到连接请求后被底层网络驱动程序唤醒*/
add_wait_queue(sock->sk->sk_sleep, &wait);
/*第5.1步:在被调度出去之前,尝试处理是否有收到连接*/
rc = sock->ops->accept(sock, newsock, O_NONBLOCK);
if (rc == -EAGAIN) {
/* 第5.2步:开始睡眠 */
schedule();
/*第5.3步:被唤醒,尝试处理收到连接*/
rc = sock->ops->accept(sock, newsock, O_NONBLOCK);
}
remove_wait_queue(sock->sk->sk_sleep, &wait);
set_current_state(TASK_RUNNING);
/*第6步:获得客户端的ip和端口*/
rc = newsock->ops->getname (newsock, (struct sockaddr *)&sin, &len,
remote ? 2 : 0);
peer_ip = ntohl (sin.sin_addr.s_addr);
peer_port = ntohs (sin.sin_port);
}
server=gethostbyname(SERVER_NAME);
sockfd=socket(AF_INET,SOCK_STREAM,0);
address.sin_family=AF_INET;
address.sin_port=htons(PORT_NUM);
memcpy(&address.sin_addr,server->h_addr,server->h_length);
connect(sockfd,&address,sizeof(address));
各层主要函数以及位置功能说明:
1)sock_write:初始化msghdr{}结构 net/socket.c
2)sock_sendmsg:net/socket.c
3)inet_sendmsg:net/ipv4/af_net.c
4)tcp_sendmsg:申请sk_buff{}结构的空间,把msghdr{}结构中的数据填入sk_buff空间。net/ipv4/tcp.c
5)tcp_send_skb:net/ipv4/tcp_output.c
6)tcp_transmit_skb:net/ipv4/tcp_output.c
7)ip_queue_xmit:net/ipv4/ip_output.c
8)ip_queue_xmit2:net/ipv4/ip_output.c
9)ip_output:net/ipv4/ip_output.c
10)ip_finish_output:net/ipv4/ip_output.c
11)ip_finish_output2:net/ipv4/ip_output.c
12)neigh_resolve_output:net/core/neighbour.c
13)dev_queue_xmit:net/core/dev.c