突發疫情但擋不住我們學習的腳步,目前疫情好轉,宅了將近一個多月的自己終於可以出去戴着口罩出去走走了!!!
接上
Linux學習筆記(一)
Linux學習筆記(二)
Linux學習筆記(三):函數、文件IO和線程
Linux學習筆記(四):信息量、同步、互斥和網絡編程
文章目錄
複習
P操作 V操作
以下主要是對服務器和客戶端複習介紹:
1、服務器:server
//建立連接
(1)socket( );//創建套接字
聲明:int socket(int domain, int type,int protocol)
int sock = socket(PF_INET,SOCK_STREAM,0);
(2)bind( );//綁定自己的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的定義
(3)listen( );//監聽是否有客戶端向服務器發起連接
聲明:int listen(int sockfd,int backlog)
sockfd:是bind後的文件描述符.
backlog:設置請求排隊的最大長度.當有多個客戶端程序和服務端相連時, 使用這個表示可以介紹的排隊長度. 函數將bind的文件描述符變爲監聽套接字.返回的情況和bind一樣.
(4)accept( );//接受客戶端的請求
聲明:int accept(int sockfd, struct sockaddr *addr,int *addrlen)
sockfd:是listen後的文件描述符.
addr,addrlen是用來給客戶端的程序填寫的,服務器端只要傳遞指針就可了. bind,listen和accept是服務器端用的函數, accept調用時,服務器端的程序會一直阻塞到有一個 客戶程序發出了連接. accept成功時返回最後的服務器端的文件描述符, 這個時候服務器端可以向該描述符寫信息了. 失敗時返回-1。
//接收數據
(5)write( );//send( );
(6)read( );//recv( );
//關閉
(7)close( );
2、客戶端:client
//建立連接
(1)socket( );
(2)connect( );//主動發起與服務器的連接
聲明:int connect(int sockfd, struct sockaddr * serv_addr,int addrlen)
sockfd:socket返回的文件描述符.
serv_addr:儲存了服務器端的連接信息.其中sin_add是服務端的地址
addrlen:serv_addr的長度
connect函數是客戶端用來同服務端連接的.成功時返回0,sockfd是同服務端通訊的文件描述符 失敗時返回-1.
//接收數據
(3)read( );//recv();
(4)write( );//send();
//關閉
(5)close( );
(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。
服務器端:其過程是首先服務器方要先啓動,並根據請求提供相應服務:
(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自帶函數創建按鍵接槽,文本顯示
信號和槽機制就相當於回調函數。在這種機制下,程序員有兩次處理事件的機會:
- 在捕獲事件後發射信號前進行預處理(事件不符合預期可以不發射信號)
- 在槽函數中進行主要處理
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTcpSocket>
#include <QMovie>
#include <QLineEdit>
#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按鈕,如下
之後在新界面添加textEdit控件用來顯示要選擇的文件內容,選擇之後可以選擇layout佈局(點擊窗口空白部分,然後選擇界面上方的佈局方式)。
(3)案例學習
網絡編程:客戶端與服務器間的通信
ubuntu下利用ifconfig查看當前網絡下的IP地址。
打開兩個終端,分別運行服務器和客戶端的代碼:
服務器:
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include <arpa/inet.h>
#include<unistd.h>
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<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include <arpa/inet.h>
#include<unistd.h>
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;
}
運行結果:
可見服務器和客戶端之間的通信已見成效!!!!!!春暖花開
大家的三連擊是對我最大的肯定!!!大家不要吝嗇自己的鼠標或者手指。。。。。。
待續中。。。。。。