Linux学习笔记(五):网络编程、QT信号与槽机制

突发疫情但挡不住我们学习的脚步,目前疫情好转,宅了将近一个多月的自己终于可以出去戴着口罩出去走走了!!!
Linux学习笔记(五):网络编程、QT信号与槽机制_第1张图片

接上
Linux学习笔记(一)
Linux学习笔记(二)
Linux学习笔记(三):函数、文件IO和线程
Linux学习笔记(四):信息量、同步、互斥和网络编程

文章目录

  • 复习
  • (1)网络编程:
    • 1、服务器server接收和发送数据
    • 2、客户端client接收和发送数据
  • (2)QT编程学习
    • 1、如何创建工程
    • 2、如何利用QT自带函数创建按键接槽,文本显示
    • 2、如何利用UI自动手动创建按键和文本
  • (3)案例学习
    • 网络编程:客户端与服务器间的通信

复习

P操作 V操作

以下主要是对服务器和客户端复习介绍:

1、服务器:server

//建立连接1socket( );//创建套接字
	声明:int socket(int domain, int type,int protocol)
	int sock = socket(PF_INET,SOCK_STREAM,0;2bind( );//绑定自己的IP
	声明:int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
	bind(sock,(struct sockaddr*)(&myaddr),sizeof(myaddr));
		sockfd:是由socket调用返回的文件描述符.
		addrlen:是sockaddr结构的长度.
		my_addr:是一个指向sockaddr的指针. 在中有 sockaddr的定义
(3listen( );//监听是否有客户端向服务器发起连接
	声明:int listen(int sockfd,int backlog)
		sockfd:是bind后的文件描述符.
		backlog:设置请求排队的最大长度.当有多个客户端程序和服务端相连时, 使用这个表示可以介绍的排队长度. 函数将bind的文件描述符变为监听套接字.返回的情况和bind一样.4accept( );//接受客户端的请求
	声明:int accept(int sockfd, struct sockaddr *addr,int *addrlen)
		sockfd:是listen后的文件描述符.
		addr,addrlen是用来给客户端的程序填写的,服务器端只要传递指针就可了. bind,listen和accept是服务器端用的函数, accept调用时,服务器端的程序会一直阻塞到有一个 客户程序发出了连接. accept成功时返回最后的服务器端的文件描述符, 这个时候服务器端可以向该描述符写信息了. 失败时返回-1//接收数据5write( );//send( );6read( );//recv( );
//关闭7close( );

2、客户端:client

//建立连接1socket( );2connect( );//主动发起与服务器的连接
	声明:int connect(int sockfd, struct sockaddr * serv_addr,int addrlen)
		sockfd:socket返回的文件描述符.
		serv_addr:储存了服务器端的连接信息.其中sin_add是服务端的地址
		addrlen:serv_addr的长度
		connect函数是客户端用来同服务端连接的.成功时返回0,sockfd是同服务端通讯的文件描述符 失败时返回-1.
//接收数据3read( );//recv();4write( );//send();
//关闭 5close( );

(1)网络编程:

什么是网络编程呢?????
就是两个进程,跨计算机,他俩需要通讯的话,需要通过网络对接起来。这就是 socket 的作用。打个比方吧,两个进程在两个计算机上,需要有一个进程做被动方,叫做服务器。另一个做主动方,叫做客户端。他们位于某个计算机上,叫做主机 host ,在网络上有自己的 ip 地址。一个计算机上可以有多个进程作为服务器,但是 ip 每个机器只有一个,所以通过不同的 port 数字加以区分。因此,服务器程序需要绑定在本机的某个端口号上。客户端需要声明自己连接哪个地址的那个端口。两个进程通过网络建立起通讯渠道,然后就可以通过 recv send 来收发一些信息,完成通讯。所以 socket 就是指代承载这种通讯的系统资源的标识。

通俗易懂的话转自:https://www.zhihu.com/question/29637351/answer/110219546

客户/服务器模式在TCP/IP网络应用中,通信的两个进程间相互作用的主要模式是客户/服务器(Client/Server, C/S)模式,即客户向服务器发出服务请求,服务器接收到请求后,提供相应的服务。
客户/服务器模式的建立基于以下两点:
(1)首先,建立网络的起因是网络中软硬件资源、运算能力和信息不均等,需要共享,从而造就拥有众多资源的主机提供服务,资源较少的客户请求服务这一非对等作用。
(2)其次,网间进程通信完全是异步的,相互通信的进程间既不存在父子关系,又不共享内存缓冲区,因此需要一种机制为希望通信的进程间建立联系,为二者的数据交换提供同步,这就是基于客户/服务器模式的TCP/IP。
Linux学习笔记(五):网络编程、QT信号与槽机制_第2张图片
服务器端:其过程是首先服务器方要先启动,并根据请求提供相应服务:
(1)打开一通信通道并告知本地主机,它愿意在某一公认地址上的某端口(如FTP的端口可能为21)接收客户请求;
(2)等待客户请求到达该端口;
(3)接收到客户端的服务请求时,处理该请求并发送应答信号。接收到并发服务请求,要激活一新进程来处理这个客户请求(如UNIX系统中用fork、exec)。新进程处理此客户请求,并不需要对其它请求作出应答。服务完成后,关闭此新进程与客户的通信链路,并终止。
(4)返回第(2)步,等待另一客户请求。
(5)关闭服务器

Server:
      int sock = socket(PF_INET,SOCK_STREAM,0);
      bind(sock,(struct sockaddr*)(&myaddr),sizeof(myaddr));
      struct sockaddr_in myaddr;
      myaddr.sin_family = PF_INET;
      myaddr.sin_port = htons(8888);
      myaddr.sin_addr.s_addr = inet_addr("192.168.13.119");
      listen(sock,7);
      int connfd = accept(sock,NULL,NULL);

客户端
(1)打开一通信通道,并连接到服务器所在主机的特定端口;
(2)向服务器发服务请求报文,等待并接收应答;继续提出请求;
(3)请求结束后关闭通信通道并终止。

client:
      connect(sock,(struct sockaddr*)(&seraddr),sizeof(seraddr));
      send(sock,”hello”,10,0);
      recv(sock,buf,sizeof(buf),0);
      close(sock);

1、服务器server接收和发送数据

创建套接字:Int sock = socket(PF_INET,SOCK_STREAM,0);
绑定自己的IP:bind(sock,(struct sockaddr*)(&myaddr),sizeof(myaddr));
主动发起与服务器的连接:struct sockaddr_in myaddr;
                      myaddr.sin_family = PF_INET;
                      myaddr.sin_port = htons(8888);
                      myaddr.sin_addr.s_addr = inet_addr("192.168.13.119");
监听:listen(sock,7);
接受请求:int connfd = accept(sock,NULL,NULL);
发送数据:send(sock,”hello”,10,0);
接收数据:recv(sock,buf,sizeof(buf),0);

2、客户端client接收和发送数据

发送数据:send(sock,”hello”,10,0);
接收数据:recv(sock,buf,sizeof(buf),0);

(2)QT编程学习

1、如何创建工程

特别需要注意的是linux下安装QT需添加的环境配置
1、 在【终端】中执行如下命令:sudo gedit /etc/profile
2、添加如下内容:

针对32位的系统配置:

export QTDIR=/wyj/Qt5.4.1/5.4
export PATH=$QTDIR/gcc/bin:$PATH
export LD_LIBRARY_PATH=$QTDIR/gcc/lib:$LD_LIBRARY_PATH

针对64位的系统配置:

export QTDIR=/opt/Qt5.4.1/5.4
export PATH=$QTDIR/gcc_64/bin:$PATH
export LD_LIBRARY_PATH=$QTDIR/gcc_64/lib:$LD_LIBRARY_PATH

(1)打开Qt Creator,点击New Project,创建一个新项目:Application->Qt Widgets Appliccation;
(2)项目名称和创建路径自己设置;
(3)Kit Selection选择gcc交叉编译器;
(4)如果系统没有自带openGL库时,在做带有3D效果的界面会报错,手动安装openGL。首先修改系统设置----软件和更新----下载自----中国的服务器。

2、如何利用QT自带函数创建按键接槽,文本显示

信号和槽机制就相当于回调函数。在这种机制下,程序员有两次处理事件的机会:

  1. 在捕获事件后发射信号前进行预处理(事件不符合预期可以不发射信号)
  2. 在槽函数中进行主要处理
#ifndef WIDGET_H
#define WIDGET_H

#include 
#include 
#include 
#include 
#include "JasonQt/JasonQt_Vop.h"

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private slots:
	// 连接完成函数
    void connectDone();

    void recvdo();
	// 按钮的槽函数
    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

    void on_pushButton_3_clicked();

    void on_pushButton_5_clicked();

    void on_pushButton_6_clicked();

    void on_pushButton_7_clicked();

    void on_pushButton_4_clicked();

    void on_pushButton_4_pressed();

    void on_pushButton_4_released();

private:
	// tcp连接函数
    void tcpConnect();
    bool Data_parsing(QByteArray);
private:
    Ui::Widget *ui;
    QTcpSocket tcpSocket,pic_socket;
    QMovie *movie;
    QLineEdit *line;
    JasonQt_Vop::BaiduVop m_baiduVop;
    unsigned int piclen;
    char picbuf[1024 * 1024 - 4];
};

#endif // WIDGET_H

2、如何利用UI自动手动创建按键和文本

在mainwindow.ui界面,添加一个pushbutton按钮,如下
Linux学习笔记(五):网络编程、QT信号与槽机制_第3张图片
之后在新界面添加textEdit控件用来显示要选择的文件内容,选择之后可以选择layout布局(点击窗口空白部分,然后选择界面上方的布局方式)。

(3)案例学习

网络编程:客户端与服务器间的通信

ubuntu下利用ifconfig查看当前网络下的IP地址。
打开两个终端,分别运行服务器和客户端的代码:

服务器:

#include
#include
#include
#include 
#include

int main(){
    /*1.创建套i接字*/
   int sock = socket(PF_INET,SOCK_STREAM,0);
    if(sock < 0){
        printf("socket error\n");
        return -1;
    }
    printf("socket success\n");
    /*2.绑定本地IP*/
    struct sockaddr_in myaddr;
    myaddr.sin_family = PF_INET;
    myaddr.sin_port = htons(8888);// 设置端口号,我这里设置的是8888
    myaddr.sin_addr.s_addr = inet_addr("xxx.xxx.xx.xxx");// 设置自己当前网端下的IP地址

    if(0 > bind(sock,(struct sockaddr*)(&myaddr),sizeof(myaddr))){
        printf("bind error\n");
        return -1;
    }
    printf("bind success\n");
    /*3.监听*/
    if(0 > listen(sock,10)){
        printf("listen error\n");
        return -1;
    }
    printf("listen success\n");
    /*4.接受链接请求*/
    int connfd = accept(sock,NULL,NULL);
    if(connfd < 0){
        printf("accept error\n");
        return -1;
    }
    printf("accept success\n");
    /*5.数据收发*/
    //send()/recv();
    char buf[20];
    gets(buf);
    int ret = send(connfd,buf,sizeof(buf),0);
    if(ret < 0){
        printf("send error\n");
        return -1;
    }
    printf("send success\n");
    /*6.关闭套接字*/
    close(connfd);
    close(sock);
return 0;
}

客户端:

#include
#include
#include
#include 
#include

int main(){
    /*1.创建套接字*/
   int sock = socket(PF_INET,SOCK_STREAM,0);
   if(sock < 0){
        printf("sock error\n");
        return -1;
    }
    printf("sock success\n");
    /*2.主动发起与服务器的连接*/
    struct sockaddr_in seraddr;
    seraddr.sin_family = PF_INET;
    seraddr.sin_port = htons(8888);
    seraddr.sin_addr.s_addr = inet_addr("xxx.xxx.xx.xxx");// 一定与服务器的IP地址一样
    if(0 > connect(sock,(struct sockaddr*)(&seraddr),sizeof(seraddr))){
        printf("connect errorr\n");
        return -1;
    }
    printf("connect success\n");

    /*3.数据收发*/
    char buf[20];
   int ret = recv(sock,buf,sizeof(buf),0);
    if(ret < 0){
        printf("recv error\n");
        return -1;
    }
    printf("recv:%s\n",buf);
    /*4.关闭套接字*/
    close(sock);
    return 0;
}

运行结果:

Linux学习笔记(五):网络编程、QT信号与槽机制_第4张图片
可见服务器和客户端之间的通信已见成效!!!!!!春暖花开
Linux学习笔记(五):网络编程、QT信号与槽机制_第5张图片

大家的三连击是对我最大的肯定!!!大家不要吝啬自己的鼠标或者手指。。。。。。

待续中。。。。。。

你可能感兴趣的:(QT学习,Linux)