Linux下使用套接口和GTK编写网络通信程序

上传人:宝路 文档编号:21044583 上传时间:2017-11-23 格式:DOC 页数:24 大小:324.82KB
返回 下载 相关 举报
Linux下使用套接口和GTK编写网络通信程序_第1页
第1页 / 共24页
Linux下使用套接口和GTK编写网络通信程序_第2页
第2页 / 共24页
Linux下使用套接口和GTK编写网络通信程序_第3页
第3页 / 共24页
Linux下使用套接口和GTK编写网络通信程序_第4页
第4页 / 共24页
Linux下使用套接口和GTK编写网络通信程序_第5页
第5页 / 共24页
点击查看更多>>
资源描述

《Linux下使用套接口和GTK编写网络通信程序》由会员分享,可在线阅读,更多相关《Linux下使用套接口和GTK编写网络通信程序(24页珍藏版)》请在金锄头文库上搜索。

1、1Linux 下使用套接口和 GTK 编写网络通信程序第一章、基础知识1.1 套接口1.1.1 基础知识套接口(socket)就是网络进程的 ID,其可以简单的理解为网络地址 (ip 地址)和端口号。套接口分两种,流式套接口使用 TCP 协议,数据报套接口使用 UDP 协议。在 Linux 中套接口的操作类似于文件描述符,可以像操作文件一样操作他们。在 Linux 中使用套接口发送数据要注意字节顺序的问题,在网络传输中,是以高字节在前(big endian)的方式传送的,而本机解析这些数据,是和 CPU 的结构有关,在传输到网络之前,需将套接口数据结构sockaddr_in 中的网络地址和端口

2、转换为高字节在前的形式。套接口的基本操作有绑定、连接、监听、应答、发送、接受、关闭等,以客户/服务器为主的网络机制其用 socket 进行 TCP 服务的简化图 1-1。一般给套接口分配的文件描述符从 3 开始,0 为默认输入, 1 为默认输出,2 为错误默认输出,这三个描述符固定分配给系统使用,如果将套接口文件描述符设置成相应的 1/2/3,则获得的数据则输出到相应的地方。图 1-121.1.2 关于 I/O使用套接口主要进行数据传输,不免要与 I/O 打交道。其 I/O 操作主要有四种模型:阻塞式,非阻塞,多路复用以及信号驱动。本文的程序使用的是阻塞式的 I/O,其简单但效率相对较低。阻塞

3、在套接口应用中很重要,处理不好会导致双方均处于阻塞状态,造成死锁。比如客户端进行 read 操作,但是对方迟迟不发送信息,导致 read 一直没有返回值,程序便会一直等待。1.2 GTKGTK (Gimp Tool Kit) 为 GNOME 中使用的开源界面开发程序。相应的,在 KDE 中主要使用的是 QT。GTK 使用了事件触发的结构处理用户响应,其开发包包括 GDK,支持包含 C 之内的多种编程语言1.3 Linux 下的 c 语言编写这里 Linux 下的 c 语言编辑主要使用 vi,编译程序使用 gcc。Gcc 编译过程中,有静态连接库等问题需要注意,使用的命令为gcc -std=c9

4、9 pkg-config -cflags -libs gtk+-2.0 -lpthread client.c -o clientgcc -std=c99 pkg-config -cflags -libs gtk+-2.0 -lpthread service.c -o service在处理字符串的时候,多应用 stdlib.h 和 string.h 里的标准库函数,区分指向常量区域的字符串指针以及字符串数组之间的区别,明确字符串数组的赋值方法(单个元素赋值或用strcat stpcpy),在 Linux 条件下,没有 itoa 函数将整型变为字符型,可以使用 sprintf 函数。1.4 多线程

5、一个进程(process)派生另一个进程称为多进程,其相比单一进程具有较高的灵活性,能够更有效地利用 CPU,但是其代价为较大的内存占用以及麻烦的进程间通信,在这样的前提下产生了多线程。多进程和多线程的区别在于,多线程中的子线程可以访问共享内存区域中的数据,简化了线程间的通信,提高了程序特别是用户界面程序的响应。但是在使用线程中要注意同时访问变量的问题,应该使用一定的机制(比如互斥锁 mutex),让各个子线程以串行的方式访问并修改内存中的数据,避免出现内存使用冲突的问题。多个线程能够共享同一个进程代码段,共有数据(用来通讯 ),进程打开的文件描述符,信号的处理器,进程当前目录,进程用户 ID

6、 等。当然每一个线程也有其独有的东西:线程ID,寄存器值,堆栈,错误返回码,信号屏蔽码和优先级。创建线程需要 pthread.h 头文件,连接时要使用 libpthread.a 的库,这里简单讲解几个和线程有关的函数。Int pthread_create(pthread_t *tid, const pthread_attr_r *attr, void *(*func)(void*), void *arg)四个输入参数依次为线程 ID 标识符,创建线程的属性,线程将要执行的函数 -返回 void 类型指针,以及传递给函数的参数(这里,参数需是 void 类型的,int 等类别的参数需要进行转换,

7、多参数传递建议使用结构体)。3Int pthread_join(pthread_t tid, void *status)等待 tid 的线程终止,然后再执行下面的命令。Status 指针内将保存线程的返回值。pthread_t pthread_self(void)返回线程 ID。pthread_cancel 结束其他它由同一个进程产生的线程,这里注意,当子线程阻塞在 I/O 时(比如,read 等待 ),是不可以用这个函数退出次线程的,这时就要考虑使用非阻塞的 I/O 获得较高的控制权和灵活性。pthread_exit 结束线程本身。在使用 Pthread 时避免线程的资源在线程结束时不能得到

8、正确释放,从而避免产生潜在的内存泄漏问题,在对待线程结束时,要确保该线程处于 detached 状态(pthread_detach(),否着就需要调用 pthread_join()函数来对其进行资源回收。线程可以通过自身执行结束来结束,也可以通过调用 pthread_exit()来结束线程的执行。另外,线程甲可以被线程乙被动结束,通过调用 pthread_cancel()来达到目的,cancel 并不等待线程终止, 它仅仅是提出请求。可以用如下两个函数设置本线程的应答属性。int pthread_setcancelstate(int state, int *oldstate)state 取值可

9、以是 PTHREAD_CNACEL_ENABLE,这个值允许线程接收取消请求。int pthread_setcanceltype(int type, int *oldtype)设置取消的类型,type 取值可以是 PTHREAD_CANCEL_ASYNCHRONOUS,它将使得线程在接收到取消请求后立即处理。在默认的情况下,线程启动时的取消状态为 PTHREAD_CNACEL_ENABLE,取消类型为PTHREAD_CANCEL_DEFERRED。1.5 IP 地址和端口在笔者处的教育网段,每台电脑几乎都可以分配一个独立的 IP 地址,每一个学校的 IP 地址是在一段地址之间。一般一台主机只有

10、一个 IP 地址,除非有多块网卡。IP 地址分为内网地址和外网地址,内网地址用于局域网广播,多是 C 网。在网络上唯一确定一个传输数据的地址,需要 IP 地址和端口的支持。在这里的通信程序中,服务器使用固定的 IP 和端口,客户端使用自己本机的 IP 和随机分配的端口进行访问。为避免冲突,一般端口设置在 1024 之上较为合理。在 Linux 下运行 ifconfig 可以得到本机的以太网卡 IP 和本机 IP。无论系统是否接入网络,本机网络这个设备总是存在的,除非你在内核编译的时候禁止了网络支持,这是一个称为回送设备的特殊设备,它自动由 Linux 配置以提供网络的自身连接。IP 地址 12

11、7.0.0.1 是一个特殊的回送地址(即默认的本机地址) ,您可以在自己的系统上用 telnet 对 IP 地址127.0.0.1 进行测试。如果有 inetd 进程在运行的话您会从自己的机器上获得登录提示符。Linux 可以利用这个特征在进程与仿真网络之间进行通信。1.6 TCP&UDPTCP 为面向连接的协议,其保证数据能够准确且按顺序地到达,在 Socket 连接选择类型为SOCK_STREAM 时即使用此协议。由于其是面向连接的,通信时需要 listen-connect 的三步握手协议。在发送数据时,先将数据保存在缓冲区,等待对方对发送的数据进行确认后才4清楚缓冲区中的数据。其实现为数

12、据流类型的服务,需要应用程序控制数据的边界。UDP 为面向无连接的协议,其保证数据的及时性,但对消息的尺寸加以限制,且没有对准确性的保证,在 Socket 连接选择类型为 SOCK_DGRAM 时即使用此协议。其通信时不需要握手协议,发送数据时直接将数据从应用缓冲区复制到系统缓冲区中,然后子程序返回。数据包的生成由 UDP 协议实现。其缓冲区具有一定大小,为 UDP 数据报的最大长度。其实现的是数据报类型服务,采用面向记录的协议。二者比较来看,UDP 服务器通常是以循环方式对多个客户进行服务的,TCP 通常使用轮询或其他多线程的方式服务多个客户。第二章、基本实现原理2.1 基本实现结构基本的实

13、现结构如图 2-1 所示,在发送登录,刷新信息时,使用互斥锁的多线程,保证当前信息的准确性,如图 B;在发送消息的时候,使用直接转发的方式,如图 A。但这样会有一个问题,当用户数量较多时,发送的登录和刷新信息会造成其他用户的白白等待,如图 C 所示。程序内部流程框图如图 2-2用户 A用户 A1 . 发送请求信息2 .打开互斥锁处理请求关闭互斥锁3 . 发送应答信息用户 B1 . 发送对话信息2 . 直接转发3 . 转发对话信息AB用户 C用户 A用户 B用户 D用户 EC图 2-15图 2-22.2 更多的想法一个改进该问题的想法如下图所示,使用两个服务器,一个作为登录使用,另一个专门作为通

14、信交换使用,两个服务器之间进行同步。当然这种实践叫前者复杂,这里没有完成其代码。用户 G用户 F用户 H用户 L用户 A用户 B用户 D用户 E登陆服务器 对话服务器实时更新数据即将转入对话服务器图 2-36第三章、部分关键代码解释3.1 服务器代码3.1.1 关于互斥锁以下代码首行和末行分别取得互斥锁的所有权和释放有权。其他试图对数据加锁的线程将被阻塞直到当前线程释放对该数据的锁。pthread_mutex_lock(&mutex);USER_INFOin_unpack.send_from.stat = 0;USER_INFOin_unpack.send_from.sd = 0;in_unp

15、ack.tag = LOGOUT_AWK;do_pack(&in_unpack,in_pack);flag += write(new_sdin_sd,in_pack,sizeof(in_pack);sleep(0.1);pthread_mutex_unlock(&mutex);3.1.2 关于线程的参数传递pthread_create(&THREADtmp_index,NULL,do_service,(void*)flag_find);将 int 格式的 flag_find 变为 void 格式的指针传递给函数 do_service。3.1.3 关于数据结构struct msg_pack /m

16、essage pack structint tag; /msg type char size:2int send_from; /msg send from char size:8int send_to; /msg send to char size:8char key64; /key used for login char size:8char msgPACK_MSG;/msg content char size:998;定义了一个包含五个元素的结构体用于 write 和 read 时的数据结构。3.2 用户代码3.2.1 关于显示文本框内容的添加gtk_text_buffer_get_end_iter(text_buffer,&iter);gtk_text_buffer_insert(text_buffer,&iter,this is it,-1);3.2.2

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > 其它办公文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号