2022年Linux网络编程-简单的客户端和服务器通讯程序开发入门 .pdf
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_05.gif)
《2022年Linux网络编程-简单的客户端和服务器通讯程序开发入门 .pdf》由会员分享,可在线阅读,更多相关《2022年Linux网络编程-简单的客户端和服务器通讯程序开发入门 .pdf(17页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、Linux网络编程 -基础知识( 1 )1. Linux网络知识介绍1.1 客户端程序和服务端程序网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的- 客户端和服务器端. 网络程序是先有服务器程序启动,等待客户端的程序运行并建立连接. 一般的来说是服务端的程序在一个端口上监听,直到有一个客户端的程序发来了请求. 1.2 常用的命令由于网络程序是有两个部分组成,所以在调试的时候比较麻烦,为此我们有必要知道一些常用的网络命令netstat 命令 netstat是用来显示网络的连接,路由表和接口统计等网络的信息. netstat有许多的选项我们常用的选项是-an 用来显示详细的网络状态
2、.至于其它的选项我们可以使用帮助手册获得详细的情况. telnet telnet是一个用来远程控制的程序,但是我们完全可以用这个程序来调试我们的服务端程序的. 比如我们的服务器程序在监听8888端口 ,我们可以用telnet localhost 8888来查看服务端的状况. 1.3 TCP/UDP介绍TCP(Transfer Control Protocol)传输控制协议是一种面向连接的协议, 当我们的网络程序使用这个协议的时候,网络可以保证我们的客户端和服务端的连接是可靠的,安全的 . UDP(User Datagram Protocol)用户数据报协议是一种非面向连接的协议, 这种协议并不
3、能保证我们的网络程序的连接是可靠的,所以我们现在编写的程序一般是采用TCP 协议的 . Linux网络编程简单的客户端和服务器通讯程序开发入门(2 )简介:本文详细介绍了Linux下 BS 结构的客户端服务器通讯程序的开发入门,其中对重要的网络函数和结构体作了详细的说明和分析,最后给出一个简单的客户端和服务器通讯程序示例以加深理解。2. 初等网络函数介绍(TCP)Linux系统是通过提供套接字(socket)来进行网络编程的.网络程序通过socket和其它几个函数的调用, 会返回一个通讯的文件描述符,我们可以将这个描述符看成普通的文件的描述符来操作, 这就是 linux的设备无关性的好处.我们
4、可以通过向描述符读写操作实现网络之间的数据交流. 2.1 socket 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 17 页 - - - - - - - - - int socket(int domain, int type,int protocol) domain:说明我们网络程序所在的主机采用的通讯协族(AF_UNIX和 AF_INET等). AF_UNIX只能够用于单一的Unix 系统进程间通信,而 AF_INET是针对 Internet的, 因而可以允许在远程
5、主机之间通信 (当我们man socket时发现domain可选项是PF_* 而不是 AF_*, 因为 glibc 是 posix的实现所以用PF 代替了 AF, 不过我们都可以使用的). type:我们网络程序所采用的通讯协议(SOCK_STREAM,SOCK_DGRAM等) SOCK_STREAM表明我们用的是 TCP 协议 , 这样会提供按顺序的,可靠,双向 ,面向连接的比特流. SOCK_DGRAM 表明我们用的是UDP 协议 , 这样只会提供定长的,不可靠 ,无连接的通信 . protocol:由于我们指定了type, 所以这个地方我们一般只要用0 来代替就可以了socket为网络通
6、讯做基本的准备 . 成功时返回文件描述符,失败时返回 -1, 看 error可知道出错的详细情况. 2.2 bind 一旦你有一个套接字,你可能要将套接字和机器上的一定的端口关联起来。 ( 如果你想用listen()来侦听一定端口的数据 ,这是必要一步 ) 如果你只想用connect(),那么这个步骤没有必要。但是无论如何,请继续读下去。这里是系统调用bind() 的大概 : int bind(int sockfd, struct sockaddr *my_addr, int addrlen) sockfd:是由 socket调用返回的文件描述符. addrlen:是 sockaddr结构的长
7、度 . my_addr:是一个指向sockaddr的指针 . 在中有sockaddr的定义struct sockaddr unisgned short as_family; char sa_data14; ; 不过由于系统的兼容性,我们一般不用这个头文件,而使用另外一个结构(struct sockaddr_in) 来代替 . 在中有 sockaddr_in的定义struct sockaddr_in unsigned short sin_family; unsigned short int sin_port; struct in_addr sin_addr; unsigned char sin_
8、zero8; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 17 页 - - - - - - - - - 我们主要使用Internet所以 sin_family一般为 AF_INET, sin_addr设置为 INADDR_ANY表示可以和任何的主机通信,sin_port是我们要监听的端口号. sin_zero8是用来填充的 . bind将本地的端口同socket返回的文件描述符捆绑在一起. 成功是返回 0, 失败的情况和socket一样2.3 listen 假如你不希
9、望与远程的一个地址相连,或者说 , 仅仅是将它踢开,那你就需要等待接入请求并且用各种方法处理它们。处理过程分两步 :首先 ,你听 -listen(),然后 ,你接受 -accept() ( 请看下面的内容) 。除了要一点解释外,系统调用listen 也相当简单。int listen(int sockfd, int backlog); sockfd 是调用socket() 返回的套接字文件描述符。backlog 是在进入队列中允许的连接数目。什么意思呢 ? 进入的连接是在队列中一直等待直到你接受(accept() 请看下面的文章 )连接。它们的数目限制于队列的允许。大多数系统的允许数目是 20,
10、 你也可以设置为5 到 10 。和别的函数一样 ,在发生错误的时候返回-1, 并设置全局错误变量errno 。你可能想象到了 ,在你调用listen() 前你或者要调用bind() 或者让内核随便选择一个端口。 如果你想侦听进入的连接,那么系统调用的顺序可能是这样的 : socket(); bind(); listen(); /* accept() 应该在这*/ 2.4 accept 准备好了 ,系统调用accept() 会有点古怪的地方的! 你可以想象发生这样的事情 : 有人从很远的地方通过一个你在侦听 (listen() 的端口连接(connect() 到你的机器。 它的连接将加入到等待接
11、受(accept() 的队列中。你调用accept() 告诉它你有空闲的连接。它将返回一个新的套接字文件描述符 !这样你就有两个套接字了,原来的一个还在侦听你的那个端口 , 新的在准备发送(send() 和接收( recv() 数据。这就是这个过程! int accept(int sockfd, struct sockaddr *addr,int *addrlen) sockfd:是 listen后的文件描述符 . addr, addrlen是用来给客户端的程序填写的,服务器端只要传递指针就可以了. bind,listen和 accept是服务器端用的函数, accept调用时 ,服务器端的程
12、序会一直阻塞到有一个客户程序发出了连接. accept成功时返回最后的服务器端的文件描述符,这个时候服务器端可以向该描述符写信息了. 失败时返名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 17 页 - - - - - - - - - 回-1 2.5 connect int connect(int sockfd, struct sockaddr * serv_addr,int addrlen) sockfd:socket返回的文件描述符. serv_addr:储存了服务器
13、端的连接信息.其中 sin_add是服务端的地址addrlen:serv_addr的长度connect函数是客户端用来同服务端连接的.成功时返回0,sockfd是同服务端通讯的文件描述符失败时返回 -1. 现在我们假设你是个telnet 程序。你的用户命令你得到套接字的文件描述符。你听从命令调用了socket()。下一步,你的用户告诉你通过端口23( 标准 telnet 端口 ) 连接到 132.241.5.10。你该怎么做呢? 幸运的是 ,你正在阅读connect()-如何连接到远程主机这一章。你可不想让你的用户失望。connect() 系统调用是这样的: #include #include
14、 int connect(int sockfd, struct sockaddr *serv_addr, int addrlen); sockfd 是系统调用socket() 返回的套接字文件描述符。serv_addr 是 保存着目的地端口和IP 地址的数据结构struct sockaddr。addrlen 设置 为 sizeof(struct sockaddr)。想知道得更多吗 ?让我们来看个例子: #include #include #include #define DEST_IP 132.241.5.10 #define DEST_PORT 23 main() int sockfd; s
15、truct sockaddr_in dest_addr; /* 目的地址 */ sockfd = socket(AF_INET, SOCK_STREAM, 0); /* 错误检查*/ dest_addr.sin_family = AF_INET; /* host byte order */ dest_addr.sin_port = htons(DEST_PORT); /* short, network byte order */ dest_addr.sin_addr.s_addr = inet_addr(DEST_IP); bzero(&(dest_addr.sin_zero),; /* ze
16、ro the rest of the struct */ /* dont forget to error check the connect()! */ connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 17 页 - - - - - - - - - . 2.6 重要的结构题介绍首先是简单的一个:socket描述符。它是下面的类型:
17、int 仅仅是一个常见的int 。从现在起 ,事情变得不可思议了,而你所需做的就是继续看下去。注意这样的事实 :有两种字节排列顺序: 重要的字节( 有时叫octet,即八位位组 ) 在前面 ,或者不重要的字节在前面。前一种叫“ 网络字节顺序(Network Byte Order) ” 。有些机器在内部是按照这个顺序储存数据,而另外一些则不然。当我说某数据必须按照NBO 顺序 ,那么你要调用函数( 例如 htons() )来将它从本机字节顺序(Host Byte Order) 转换过来。如果我没有提到NBO, 那么就让它保持本机字节顺序。我的第一个结构 ( 在这个技术手册TM 中)-struct
18、 sockaddr.。这个结构为许多类型的套接字储存套接字地址信息 : struct sockaddr unsigned short sa_family; /* 地址家族 , AF_xxx */ char sa_data14; /*14字节协议地址 */ ; sa_family 能够是各种各样的类型,但是在这篇文章中都是AF_INET。 sa_data包含套接字中的目标地址和端口信息。这好像有点不明智。为了处理 struct sockaddr,程序员创造了一个并列的结构: struct sockaddr_in (in 代表 Internet。 ) struct sockaddr_in shor
19、t int sin_family; /* 通信类型*/ unsigned short int sin_port; /* 端口 */ struct in_addr sin_addr; /* Internet 地址 */ unsigned char sin_zero8; /* 与 sockaddr结构的长度相同*/ ; 用这个数据结构可以轻松处理套接字地址的基本元素。注意sin_zero (它被加入到这个结构,并且长度和struct sockaddr 一样 ) 应该使用函数bzero() 或 memset() 来全部置零。同时 ,这一重要的字节,一个指向sockaddr_in结构体的指针也可以被指
20、向结构体sockaddr并且代替它。这样的话即使socket() 想要的是struct sockaddr *,你仍然可以使 用struct sockaddr_in,并 且 在 最 后 转 换 。 同 时 , 注 意sin_family 和struct sockaddr 中 的sa_family 一致并能够设置为AF_INET。最后 ,sin_port和 sin_addr 必须是网络字节顺序(Network Byte Order)! 你也许会反对道: 但是 ,怎么让整个数据结构struct in_addr sin_addr 按照网络字节顺序呢? 要知道这个问题的答案,我们就要仔细的看一看这个数据
21、结构 : struct in_addr, 有这样一个联合(unions): /* Internet 地址(一个与历史有关的结构) */ 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 17 页 - - - - - - - - - struct in_addr unsigned long s_addr; ; 它曾经是个最坏的联合,但是现在那些日子过去了。如果你声明ina 是数据结构struct sockaddr_in 的实例 ,那么ina.sin_addr.s_addr 就
22、储 存 4 字节的IP 地址 ( 使用网络字节顺序) 。如果你不幸的系统使用的还是恐 怖的联合struct in_addr ,你还是可以放心4 字节的IP 地址并且和上面我说的一样 (这是因为使用了“ #define”。 ) struct hostent结构体这个数据结构是这样的: struct hostent char *h_name; char *h_aliases; int h_addrtype; int h_length; char *h_addr_list; ; #define h_addr h_addr_list0 这里是这个数据结构的详细资料:struct hostent: h_
23、name 地址的正式名称。h_aliases 空字节 - 地址的预备名称的指针。h_addrtype 地址类型 ; 通常是 AF_INET 。h_length 地址的比特长度。h_addr_list 零字节 - 主机网络地址指针。网络字节顺序。h_addr - h_addr_list中的第一地址。2.7 本机转换我们现在到了新的章节。我们曾经讲了很多网络到本机字节顺序的转换,现在可以实践了! 你能够转换两种类型: short ( 两个字节 )和 long (四个字节 ) 。这个函数对于变量类型unsigned 也适用。假设你想将short 从本机字节顺序转换为网络字节顺序。用h 表示本机(ho
24、st),接着是to, 然后用n 表示 网络(network),最后用s 表示short: h-to-n-s, 或者 htons() (Host to Network Short)。太简单了 . 如果不是太傻的话,你一定想到了由n,h,s,和l 形成的正确组合 ,例如这里肯定没有stolh() (Short to Long Host) 函数 ,不仅在这里没有 ,所有场合都没有。但是这里有: htons()-Host to Network Short htonl()-Host to Network Long ntohs()-Network to Host Short ntohl()-Network
25、 to Host Long 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 6 页,共 17 页 - - - - - - - - - 现在 ,你可能想你已经知道它们了。你也可能想:“ 如果我想改变char 的顺序要怎么办呢?” 但是你也许马上就想到 , “ 用不着考虑的 ” 。你也许会想到 : 我的 68000 机器已经使用了网络字节顺序,我没有必要去调用htonl() 转换 IP 地址。你可能是对的 ,但是当你移植你的程序到别的机器上的时候 ,你的程序将失败。可移植性!这里是Uni
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 2022年Linux网络编程-简单的客户端和服务器通讯程序开发入门 2022 Linux 网络 编程 简单 客户端 服务器 通讯 程序 开发 入门
![提示](https://www.taowenge.com/images/bang_tan.gif)
限制150内