1、原理与使用
一般而言,使用socket的接口创建一个socket,用如下构造函数。
int socket(int domain, int type, int protocol)
domain 就是指 PF_INET、PF_INET6 以及 PF_LOCAL 等,表示IPV4,IPV6或者域套接字等套接字类型。
type 可用的值是:SOCK_STREAM: 表示的是字节流,对应 TCP;SOCK_DGRAM:表示的是数据报,对应 UDP;SOCK_RAW: 表示的是原始套接字。
下面我们看一个建立的服务端创建的例子,首先使用socket接口创建一个socket,然后调用bind函数绑定本地端口。
int make_socket (uint16_t port){int sock;struct sockaddr_in name;/* 创建字节流类型的IPV4 socket. */sock = socket (PF_INET, SOCK_STREAM, 0);if (sock < 0){perror ("socket");exit (EXIT_FAILURE);}/* 绑定到port和ip. */name.sin_family = AF_INET; /* IPV4 */name.sin_port = htons (port); /* 指定端口 */name.sin_addr.s_addr = htonl (INADDR_ANY); /* 通配地址 *//* 把IPV4地址转换成通用地址格式,同时传递长度 */if (bind(sock, (struct sockaddr *) &name, sizeof (name))< 0){perror ("bind");exit (EXIT_FAILURE);}return sock;}//然后服务端需要listen端口,accept连接
2、Linux源码走读
SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol){int retval; struct socket *sock; int flags;......if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;retval = sock_create(family, type, protocol, &sock);//①......retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));......return retval;}

int __sock_create(struct net *net, int family, int type,int protocol,struct socket **res, int kern){int err;struct socket *sock;const struct net_proto_family *pf;......sock = sock_alloc();......sock->type = type;......pf = rcu_dereference(net_families[family]);......err = pf->create(net, sock, protocol, kern);......*res = sock;return 0;}
static const struct net_proto_family inet_family_ops = {.family = PF_INET,.create = inet_create,//这个用于socket系统调用创建......}
static int inet_create(struct net *net, struct socket *sock,int protocol, int kern){struct sock *sk;struct inet_protosw *answer;struct inet_sock *inet;struct proto *answer_prot;unsigned char answer_flags;int try_loading_module = 0;int err;/* Look for the requested type/protocol pair. */lookup_protocol:list_for_each_entry_rcu(answer, &inetsw[sock->type], list) {err = 0;/* Check the non-wild match. yishuihan*/if (protocol == answer->protocol) {if (protocol != IPPROTO_IP)break;} else {/* Check for the two wild cases. */if (IPPROTO_IP == protocol) {protocol = answer->protocol;break;}if (IPPROTO_IP == answer->protocol)break;}err = -EPROTONOSUPPORT;}......sock->ops = answer->ops;answer_prot = answer->prot;answer_flags = answer->flags;......sk = sk_alloc(net, PF_INET, GFP_KERNEL, answer_prot, kern);......}
static int __init inet_init(void){/* Register the socket-side information for inet_create. */for (r = &inetsw[0]; r < &inetsw[SOCK_MAX]; ++r)INIT_LIST_HEAD(r);for (q = inetsw_array; q < &inetsw_array[INETSW_ARRAY_LEN]; ++q)inet_register_protosw(q);//省略其他代码... yishuihan}
static struct inet_protosw inetsw_array[] ={{.type = SOCK_STREAM,.protocol = IPPROTO_TCP,.prot = &tcp_prot,.ops = &inet_stream_ops,.flags = INET_PROTOSW_PERMANENT|INET_PROTOSW_ICSK,},//省略其他协议,比如UDP等.... yishuihan}
struct proto tcp_prot = {.name = "TCP",.owner = THIS_MODULE,.close = tcp_close,.connect = tcp_v4_connect,.disconnect = tcp_disconnect,.accept = inet_csk_accept,.ioctl = tcp_ioctl,.init = tcp_v4_init_sock,.destroy = tcp_v4_destroy_sock,.shutdown = tcp_shutdown,.setsockopt = tcp_setsockopt,.getsockopt = tcp_getsockopt,.keepalive = tcp_set_keepalive,.recvmsg = tcp_recvmsg,.sendmsg = tcp_sendmsg,.sendpage = tcp_sendpage,.backlog_rcv = tcp_v4_do_rcv,.release_cb = tcp_release_cb,.hash = inet_hash,.get_port = inet_csk_get_port,......}
3 总结
文章转载自码农的修炼之道,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




