目錄
一、talk程序的運用&Linux進程間通信程序的編寫
1.1使用talk程序和其他用戶交流
1.2用c語言寫一個linux進程之間通信(聊天)的簡單程序
1.服務器端程序socket_server.c編寫
2.客戶端程序socket_client.c編寫
3.程序編譯與使用
二、編寫一個打開圖片進行特效顯示的代碼 test1.cpp
2.1 下載安裝 opencv
1 .下載安裝包并解壓
2 .使用 cmake安裝opencv
3. 使用make創建并編譯安裝
4. 配置環境
2.2 打開圖片進行特效顯示
1 .示例圖片
2. 具體過程
3 .相關問題
一、talk程序的運用&Linux進程間通信程序的編寫
1.1使用talk程序和其他用戶交流
首先我們通過who指令查詢,可以看到當前已經登錄用戶信息和終端
然后輸入talk指令連接對應用戶進行通信
talk username pts/
然后等待對方用戶連接
對面用戶會收到如下信息,然后輸入指令
talk username
完成后雙方可進行文字交流
白線上面部分為我發送的信息,下面部分為接收到的信息
交流結束后可通過“Ctrl+C"退出
但是當我們嘗試在talk程序下輸入中文進行交流時,會出現中文亂碼。所以接下來我們嘗試自己編寫一個c語言程序,實現Linux進程之間的通信。
1.2用c語言寫一個linux進程之間通信(聊天)的簡單程序
1.服務器端程序socket_server.c
編寫
通過nano socket_server.c
新建服務器端程序文件,并進行如下代碼編寫。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
?
#define PORT 8080
#define BUFFER_SIZE 1024
?
void *handle_client(void *arg) {int client_socket = *((int *)arg);char buffer[BUFFER_SIZE];int bytes_read;while (1) {bytes_read = read(client_socket, buffer, BUFFER_SIZE);if (bytes_read <= 0) {break;}buffer[bytes_read] = '\0';printf("Received: %s", buffer);printf("Enter reply (or 'exit' to quit): ");fgets(buffer, BUFFER_SIZE, stdin);if (strncmp(buffer, "exit", 4) == 0) {write(client_socket, "Server exiting...", 17);break;}write(client_socket, buffer, strlen(buffer));}close(client_socket);pthread_exit(NULL);
}
?
int main() {int server_fd, client_socket;struct sockaddr_in address;int opt = 1;int addrlen = sizeof(address);pthread_t thread_id;// 創建socket文件描述符if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {perror("socket failed");exit(EXIT_FAILURE);}// 設置socket選項if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {perror("setsockopt");exit(EXIT_FAILURE);}address.sin_family = AF_INET;address.sin_addr.s_addr = INADDR_ANY;address.sin_port = htons(PORT);// 綁定socket到端口if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {perror("bind failed");exit(EXIT_FAILURE);}// 開始監聽if (listen(server_fd, 3) < 0) {perror("listen");exit(EXIT_FAILURE);}printf("Server started on port %d. Waiting for connections...\n", PORT);while (1) {// 接受新連接if ((client_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {perror("accept");continue;}printf("New connection from %s\n", inet_ntoa(address.sin_addr));// 為每個客戶端創建新線程if (pthread_create(&thread_id, NULL, handle_client, (void *)&client_socket) < 0) {perror("could not create thread");continue;}// 分離線程,使其結束后自動釋放資源pthread_detach(thread_id);}close(server_fd);return 0;
}
2.客戶端程序socket_client.c
編寫
通過nano socket_client.c
新建客戶端代碼文件,并進行如下代碼編寫
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
?
#define BUFFER_SIZE 1024
?
void *receive_messages(void *arg) {int sock = *((int *)arg);char buffer[BUFFER_SIZE];int bytes_read;while (1) {bytes_read = read(sock, buffer, BUFFER_SIZE);if (bytes_read <= 0) {printf("Server disconnected\n");exit(EXIT_SUCCESS);}buffer[bytes_read] = '\0';printf("\nReceived: %s", buffer);printf("Enter message (or 'exit' to quit): ");fflush(stdout);}return NULL;
}
?
int main(int argc, char const *argv[]) {if (argc != 2) {printf("Usage: %s <server_ip>\n", argv[0]);exit(EXIT_FAILURE);}int sock = 0;struct sockaddr_in serv_addr;char buffer[BUFFER_SIZE] = {0};pthread_t thread_id;// 創建socketif ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {perror("socket creation error");exit(EXIT_FAILURE);}serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(8080);// 將IP地址從字符串轉換為二進制形式if (inet_pton(AF_INET, argv[1], &serv_addr.sin_addr) <= 0) {perror("invalid address");exit(EXIT_FAILURE);}// 連接服務器if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {perror("connection failed");exit(EXIT_FAILURE);}printf("Connected to server at %s\n", argv[1]);// 創建接收消息的線程if (pthread_create(&thread_id, NULL, receive_messages, (void *)&sock) < 0) {perror("could not create thread");exit(EXIT_FAILURE);}// 主線程處理發送消息printf("Enter message (or 'exit' to quit): ");while (fgets(buffer, BUFFER_SIZE, stdin)) {if (strncmp(buffer, "exit", 4) == 0) {write(sock, "Client exiting...", 17);break;}write(sock, buffer, strlen(buffer));printf("Enter message (or 'exit' to quit): ");}close(sock);return 0;
}
3.程序編譯與使用
在服務器和客戶端機器上分別編譯:
# 服務器端
gcc socket_server.c -o server -lpthread
?
# 客戶端
gcc socket_client.c -o client -lpthread
接下來我們進行通訊嘗試:
在服務器機器上啟動服務器程序:
./server
在客戶端機器上啟動客戶端程序,指定服務器IP地址:
./client <服務器IP地址>
二、編寫一個打開圖片進行特效顯示的代碼 test1.cpp
2.1 下載安裝 opencv
1 .下載安裝包并解壓
下載安裝資源壓縮包
將下載好的壓縮包opencv-3.4.11放在主目錄文件夾下
解壓縮(打開虛擬機終端,輸入命令 unzip opencv-3.4.11.zip)
unzip opencv-3.4.11.zip
解壓縮以后主目錄文件夾如下:
進入到解壓后的文件夾中
cd opencv-3.4.11
2 .使用 cmake安裝opencv
(1)首先進入 root 用戶,并更新一下
sudo su
sudo apt-get update
(2)執行以下命令安裝 cmake
sudo apt-get install cmake
這里直接按enter鍵默認繼續安裝
(3)cmake安裝完成
(4)安裝依賴庫
sudo apt-get install build-essential libgtk2.0-dev libavcodec-dev libavformat-dev libjpeg.dev libtiff5.dev libswscale-dev libjasper-dev
(5)創建build文件夾,進入build文件夾
(6)使用cmake 編譯參數
cmake ..
運行結果如下:
3. 使用make創建并編譯安裝
(1)在build文件夾下進行
輸入以下命令
sudo make
(2)編譯完成
(3)安裝
輸入以下命令
sudo make install
(4)安裝完成
4. 配置環境
(1)修改 opencv.conf文件,打開后的文件是空的,添加opencv庫的安裝路徑:/usr/local/lib
輸入以下命令
sudo gedit /etc/ld.so.conf.d/opencv.conf
輸入路徑/usr/local/lib 并保存,記得點小叉叉退出文件編輯界面
出現警告是正常的
(2)更新系統共享鏈接
sudo ldconfig
(3)配置bash,修改 bash.bashrc 文件
輸入以下命令
sudo gedit /etc/bash.bashrc
(4)在文件末尾加入
PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig export PKG_CONFIG_PATH
(5)然后執行以下命令使得配置生效
source /etc/bash.bashrc
(6)輸入以下命令更新
sudo updatedb
我輸入之后顯示找不到命令,好像是之前有個軟件包沒安裝成功
解決方法:
運行以下命令安裝 mlocate軟件包
sudo apt-get update sudo apt-get install mlocate
手動運行 updatedb
sudo updatedb
(7)查看 opencv 的版本信息
如下圖所示,說明安裝成功
2.2 打開圖片進行特效顯示
1 .示例圖片
2. 具體過程
(1)新建文件夾code
輸入以下命令創建新的文件夾
mkdir code cd code
(2)新建文件 test1.cpp
輸入以下命令新建 test1.cpp 文件
vim test1.cpp
(3)test1.cpp代碼
\#include <opencv2/highgui.hpp>
\#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{CvPoint center;double scale = -3; IplImage* image = cvLoadImage("lena.jpg");argc == 2? cvLoadImage(argv[1]) : 0;cvShowImage("Image", image);if (!image) return -1; center = cvPoint(image->width / 2, image->height / 2);for (int i = 0;i<image->height;i++)for (int j = 0;j<image->width;j++) {double dx = (double)(j - center.x) / center.x;double dy = (double)(i - center.y) / center.y;double weight = exp((dx*dx + dy*dy)*scale);uchar* ptr = &CV_IMAGE_ELEM(image, uchar, i, j * 3);ptr[0] = cvRound(ptr[0] * weight);ptr[1] = cvRound(ptr[1] * weight);ptr[2] = cvRound(ptr[2] * weight);}Mat src;Mat dst;src = cvarrToMat(image);cv::imwrite("test.png", src);cvNamedWindow("test",1); ? imshow("test", src);cvWaitKey();return 0;
}
輸入代碼以后,按Esc 輸入 :wq保存退出
vim修改代碼,按i進入插入模式;按Esc再輸入 :wq 保存并退出
(4)把圖片粘貼到code目錄下
(5)編譯 test1.cpp 文件
g++ test1.cpp -o test pkg-config --cflags --libs opencv
(6)運行
輸入以下命令運行
./test
運行結果
3 .相關問題
1、請解釋 gcc test1.cpp -o test1 pkg-config --cflags --libs opencv這條編譯命令,它是如何獲得opencv頭文件、鏈接lib庫文件的路徑的?
命令解析: gcc
:GNU 編譯器,用于編譯 C/C++ 程序。 test1.cpp
:源代碼文件,包含 OpenCV 的代碼。 -o test1
:指定輸出的可執行文件名稱為 test1。 pkg-config --cflags --libs opencv
:這是一個子命令用于,動態獲取 OpenCV 的編譯和鏈接參數。 pkg-config
:一個工具,用于查詢已安裝庫的編譯和鏈接參數。 --cflags
:獲取 OpenCV 的頭文件路徑(-I 參數)。 --libs
:獲取 OpenCV 的庫文件路徑(-L 參數)和庫名稱(-l 參數)。
(1)pkg-config --cflags --libs opencv
會返回 OpenCV 的頭文件路徑和庫文件路徑,例如:
-I/usr/local/include/opencv4 -L/usr/local/lib -lopencv_core -lopencv_imgproc -lopencv_highgui ...
(2)這些參數會被傳遞給 gcc,確保編譯器能夠找到 OpenCV 的頭文件和庫文件。
2、改用make+makefile方式編譯 上述程序(用變量命名格式寫makefile文件,并包括 clean選項)
將以下內容保存為 Makefile 文件,放在 code 目錄下
\# 定義變量
CXX = g++
CXXFLAGS = `pkg-config --cflags opencv`
LDFLAGS = `pkg-config --libs opencv`
SRC = test.cpp
OBJ = test.o
TARGET = test
?
\# 默認目標
all: $(TARGET)
?
\# 編譯規則
$(TARGET): $(OBJ)$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $(TARGET) $(OBJ)
?
\# 生成對象文件
$(OBJ): $(SRC)$(CXX) $(CXXFLAGS) -c $(SRC) -o $(OBJ)
?
\# 清理
clean:rm -f $(OBJ) $(TARGET)
在終端運行以下命令
cd ~/code
make
運行程序
./test
清理編譯文件
make clean
3、用cmake方式進行編譯
將以下內容保存為 CMakeLists.txt 文件,放在 ~/code 目錄下:
\# CMake 最低版本要求
cmake_minimum_required(VERSION 3.10)
?
\# 項目名稱
project(OpenCVTest)
?
\# 查找 OpenCV
find_package(OpenCV REQUIRED)
?
\# 添加可執行文件
add_executable(test test.cpp)
?
\# 鏈接 OpenCV 庫
target_link_libraries(test ${OpenCV_LIBS})
(1)在 ~/code 目錄下創建一個構建目錄并進入:
cd ~/code
mkdir build
cd build
(2)運行 cmake 和 make:
cmake ..
make
編譯完成后,可執行文件 test 會生成在 build 目錄中
(3)運行程序
./test
(4)清理
刪除 build 目錄
rm -rf ~/code/build
4、對比總結
方式 | 優點 | 適用場景 |
---|---|---|
直接 gcc | 簡單快速 | 單文件小項目 |
Makefile | 支持多文件、變量管理、增量編譯 | 中小型項目 |
CMake | 跨平臺、自動檢測依賴、適合大型項目 | 大型或跨平臺項目 |