linux内核学习之网络篇——通过socket通信
来源:互联网 发布:第三方服务商淘宝客 编辑:程序博客网 时间:2024/06/08 00:04
通过网卡,让我们能达到通信,对unix是相当的复杂,组要是socket每一层都是用了不同的通信协议,需要好多设置好多的选项。因此在/dev目录下,并没有网卡对应的文件。
socket不仅可以用于各种传输协议的IP的连接。也可以用于内核支持的所有其他地址和协议类型。
套接字是使用socket库函数生成的。然后bind函数等。
socket主要用于协议的选择,通信类型,地址族。
bind函数主要目的是给到戒子分配本地地址。该函数的传递一个sockaddr_type 的参数,定义了本地地址。因为不同地址组的地址类型是不同的。type制定了所需的地址类型。
这个时候,我们来点代码
#ifndef _LINUX_IN_H#define _LINUX_IN_H#include <linux/types.h>#include <linux/socket.h>/* Standard well-defined IP protocols. */enum { IPPROTO_IP = 0,/* Dummy protocol for TCP*/ IPPROTO_ICMP = 1,/* Internet Control Message Protocol*/ IPPROTO_IGMP = 2,/* Internet Group Management Protocol*/ IPPROTO_IPIP = 4,/* IPIP tunnels (older KA9Q tunnels use 94) */ IPPROTO_TCP = 6,/* Transmission Control Protocol*/ IPPROTO_EGP = 8,/* Exterior Gateway Protocol*/ IPPROTO_PUP = 12,/* PUP protocol*/ IPPROTO_UDP = 17,/* User Datagram Protocol*/ IPPROTO_IDP = 22,/* XNS IDP protocol*/ IPPROTO_RSVP = 46,/* RSVP protocol*/ IPPROTO_GRE = 47,/* Cisco GRE tunnels (rfc 1701,1702)*/ IPPROTO_IPV6 = 41,/* IPv6-in-IPv4 tunnelling*/ IPPROTO_ESP = 50, /* Encapsulation Security Payload protocol */ IPPROTO_AH = 51, /* Authentication Header protocol */ IPPROTO_PIM = 103,/* Protocol Independent Multicast*/ IPPROTO_COMP = 108, /* Compression Header protocol */ IPPROTO_SCTP = 132,/* Stream Control Transport Protocol*/ IPPROTO_RAW = 255,/* Raw IP packets*/ IPPROTO_MAX};/* Internet address. */struct in_addr {__u32s_addr;};#define IP_TOS1#define IP_TTL2#define IP_HDRINCL3#define IP_OPTIONS4#define IP_ROUTER_ALERT5#define IP_RECVOPTS6#define IP_RETOPTS7#define IP_PKTINFO8#define IP_PKTOPTIONS9#define IP_MTU_DISCOVER10#define IP_RECVERR11#define IP_RECVTTL12#defineIP_RECVTOS13#define IP_MTU14#define IP_FREEBIND15#define IP_IPSEC_POLICY16#define IP_XFRM_POLICY17/* BSD compatibility */#define IP_RECVRETOPTSIP_RETOPTS/* IP_MTU_DISCOVER values */#define IP_PMTUDISC_DONT0/* Never send DF frames */#define IP_PMTUDISC_WANT1/* Use per route hints*/#define IP_PMTUDISC_DO2/* Always DF*/#define IP_MULTICAST_IF32#define IP_MULTICAST_TTL 33#define IP_MULTICAST_LOOP 34#define IP_ADD_MEMBERSHIP35#define IP_DROP_MEMBERSHIP36#define IP_UNBLOCK_SOURCE37#define IP_BLOCK_SOURCE38#define IP_ADD_SOURCE_MEMBERSHIP39#define IP_DROP_SOURCE_MEMBERSHIP40#define IP_MSFILTER41#define MCAST_JOIN_GROUP42#define MCAST_BLOCK_SOURCE43#define MCAST_UNBLOCK_SOURCE44#define MCAST_LEAVE_GROUP45#define MCAST_JOIN_SOURCE_GROUP46#define MCAST_LEAVE_SOURCE_GROUP47#define MCAST_MSFILTER48#define MCAST_EXCLUDE0#define MCAST_INCLUDE1/* These need to appear somewhere around here */#define IP_DEFAULT_MULTICAST_TTL 1#define IP_DEFAULT_MULTICAST_LOOP 1/* Request struct for multicast socket ops */struct ip_mreq {struct in_addr imr_multiaddr;/* IP multicast address of group */struct in_addr imr_interface;/* local IP address of interface */};struct ip_mreqn{struct in_addrimr_multiaddr;/* IP multicast address of group */struct in_addrimr_address;/* local IP address of interface */intimr_ifindex;/* Interface index */};struct ip_mreq_source {__u32imr_multiaddr;__u32imr_interface;__u32imr_sourceaddr;};struct ip_msfilter {__u32imsf_multiaddr;__u32imsf_interface;__u32imsf_fmode;__u32imsf_numsrc;__u32imsf_slist[1];};#define IP_MSFILTER_SIZE(numsrc) \(sizeof(struct ip_msfilter) - sizeof(__u32) \+ (numsrc) * sizeof(__u32))struct group_req{__u32 gr_interface;/* interface index */struct __kernel_sockaddr_storage gr_group;/* group address */};struct group_source_req{__u32 gsr_interface;/* interface index */struct __kernel_sockaddr_storage gsr_group;/* group address */struct __kernel_sockaddr_storage gsr_source;/* source address */};struct group_filter{__u32 gf_interface;/* interface index */struct __kernel_sockaddr_storage gf_group;/* multicast address */__u32 gf_fmode;/* filter mode */__u32 gf_numsrc;/* number of sources */struct __kernel_sockaddr_storage gf_slist[1];/* interface index */};#define GROUP_FILTER_SIZE(numsrc) \(sizeof(struct group_filter) - sizeof(struct __kernel_sockaddr_storage) \+ (numsrc) * sizeof(struct __kernel_sockaddr_storage))struct in_pktinfo{intipi_ifindex;struct in_addripi_spec_dst;struct in_addripi_addr;};/* Structure describing an Internet (IP) socket address. */#define __SOCK_SIZE__16/* sizeof(struct sockaddr)*/struct sockaddr_in { sa_family_tsin_family;/* Address family*/ unsigned short intsin_port;/* Port number*/ struct in_addrsin_addr;/* Internet address*/ /* Pad to size of `struct sockaddr'. */ unsigned char__pad[__SOCK_SIZE__ - sizeof(short int) -sizeof(unsigned short int) - sizeof(struct in_addr)];};
重点看红色部分,
sin_family;地址族 unsigned short int sin_port; 端口号
struct in_addr sin_addr; 网络地址。
在这里考虑到网络字节序还有大端小端的问题。
下面有个简单的例子。
使用了基本的用户函数 socket,bind,listion select 函数
<strong><span style="font-size: 18px;">首先 运行在linux 运行gcc -g -o select select.c</span></strong><pre class="cpp" name="code">/ *******select.c*********// *******Using select() for I/O multiplexing */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>/* port we're listening on */#define PORT 2020int main(int argc, char *argv[]){/*定义描述符集合 */fd_set master;/* 定义select函数可读的描述符*/fd_set read_fds;/* 服务器地址 */struct sockaddr_in serveraddr;/* 客户地址 */struct sockaddr_in clientaddr;/* 定义最大描述符数 */int fdmax;/* 监听描述符 */int listener;/* accept描述符 */int newfd;/* 缓冲 */char buf[1024];int nbytes;/* 设置 setsockopt() SO_REUSEADDR */int yes = 1;int addrlen;int i, j;/* 清除 */FD_ZERO(&master);FD_ZERO(&read_fds);/* 连接 */if((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1){perror("Server-socket() error lol!");exit(1);}printf("Server-socket() is OK...\n");/*判断地址以用 */if(setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1){perror("Server-setsockopt() error lol!");exit(1);}printf("Server-setsockopt() is OK...\n");/* bind */serveraddr.sin_family = AF_INET;serveraddr.sin_addr.s_addr = INADDR_ANY;serveraddr.sin_port = htons(PORT);memset(&(serveraddr.sin_zero), '\0', 8);if(bind(listener, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) == -1){perror("Server-bind() error lol!");exit(1);}printf("Server-bind() is OK...\n");/* listen */if(listen(listener, 10) == -1){perror("Server-listen() error lol!");exit(1);}printf("Server-listen() is OK...\n");/* 把 listener 加到 master set */FD_SET(listener, &master);/* keep track of the biggest file descriptor */fdmax = listener; /* so far, it's this one*//* 循环了 */for(;;){/* copy it */read_fds = master;if(select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1){perror("Server-select() error lol!");exit(1);}printf("Server-select() is OK...\n");/*从存在的描述符中查找要读的数据*/for(i = 0; i <= fdmax; i++){if(FD_ISSET(i, &read_fds)){ /* 得到一个... */if(i == listener){/* h处理这个的连接 */addrlen = sizeof(clientaddr);if((newfd = accept(listener, (struct sockaddr *)&clientaddr, &addrlen)) == -1){perror("Server-accept() error lol!");}else{printf("Server-accept() is OK...\n");FD_SET(newfd, &master); /* add to master set */if(newfd > fdmax){ /* keep track of the maximum */fdmax = newfd;}printf("%s: New connection from %s on socket %d\n", argv[0], inet_ntoa(clientaddr.sin_addr), newfd);}}else{/* 处理从客户端来的数据*/if((nbytes = recv(i, buf, sizeof(buf), 0)) <= 0){/* 没有数据 */if(nbytes == 0)/* 断开连接。 */printf("%s: socket %d hung up\n", argv[0], i);elseperror("recv() error lol!");/* 关闭... */close(i);/* 删除这个连接符 */FD_CLR(i, &master);}else{/* we got some data from a client*/for(j = 0; j <= fdmax; j++){/* 发给每个人! */if(FD_ISSET(j, &master)){/* 除了监听的和自己的。 */if(j != listener && j != i){if(send(j, buf, nbytes, 0) == -1)perror("send() error lol!");}}}}}}}}return 0;}</pre><br><pre></pre><pre class="cpp" name="code"><strong><span style="font-size: 18px;">然后在运行 ./select & 或者ctrl+z 让他后台运行</span></strong></pre><pre class="cpp" name="code"><span style="font-size: 18px;"><strong>开一个窗口 运行telnet localhostip 2020</strong> </span></pre><pre class="cpp" name="code"><span style="font-size: 18px;">程序如下</span></pre><pre class="cpp" name="code"></pre><p>更多文章,欢迎访问<a href="http://blog.csdn.net/wallwind">http://blog.csdn.net/wallwind</a> 转载请注明出处</p>
- linux内核学习之网络篇——通过socket通信
- ]linux内核学习之网络篇——接收分组
- linux学习之——网络 socket 编程实例
- linux内核学习之网络篇——网络物理层的设备初步
- 通过socket实现网络通信
- java学习之路——基于TCP的Socket网络通信实例
- java学习之路——基于UDP的Socket网络通信实例
- 网络基础篇——socket网络编程之UDP通信
- Linux内核工程导论——网络:Socket
- Linux内核网络协议栈8—socket监听
- linux内核学习之网络篇——TCP/IP概述
- linux内核学习之网络篇——套接字缓冲区
- linux内核学习之网络篇——IP和TCP结构体源码
- 通过Socket uevent与内核通信
- Linux之—网络通信(TCP)
- Linux之—网络通信(TCP)
- linux之socket通信
- Linux网络编程之[Socket通信的常用函数简介]
- hdu 4404 worms #by nobody
- 判断字符串是否是IPV4
- tcp连接三次握手过程中的,tcp协议栈中的函数调用关系
- asp.net 获取网站根目录总结
- 从ads到keil
- linux内核学习之网络篇——通过socket通信
- Win7下.NET应用程序System.IO.FileNotFoundException问题
- Uboot中start.S源码的指令级的详尽解析 在线版
- PHP 获取时间差函数汇总
- 结构体字节对齐
- boost test
- jQuery中load的使用
- MonkeyRunner_Testing app example(1)
- 【Author : DS & MZ】 2012 ACM-ICPC 杭州网络预赛