目录
一、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 | 跨平台、自动检测依赖、适合大型项目 | 大型或跨平台项目 |