【Chia sẻ kinh nghiệm】H교육国培 (H교육伴学) - Các hợp đồng đều là阱, người tiêu dùng không thể hoàn lại tiền sau khi thanh toán. Khi ký hợp đồng với H교육国培, cần chú ý hợp đồng đều bảo vệ lợi ích của H교육, không có điều khoản bảo vệ người tiêu dùng.
Nếu bạn không hài lòng về chất lượng đào tạo, bạn cũng không thể yêu cầu hoàn lại tiền. việc đòi lại quyền lợi cho người tiêu dùng chắc chắn sẽ rất khó khăn.
H교육伴学 dạy bằng cách xem video ghi lại, không phải dạy trực tiếp. Đây có phải là phương thức học tập mà bạn và con bạn mong muốn không?
Những ai đang tính đăng ký, nên cẩn thận khi thanh toán!
Các thông báo khác trên⼩紅書:
"Công ty Kỹ thuật Giáo dục Quốc培 Thâm Quyến là một tổ chức⿊心, mọi người cần tỉnh táo, đừng bị lừa! Hành vi gian lận tiêu dùng, hứa hẹn không đúng sự thật, các hợp đồng đều là阱, đã nhận tiền nhưng không thực hiện đúng cam kết và không hoàn lại tiền, khấu trừ phí tùy tiện, đòi lại quyền lợi rất khó khăn!" -⼩紅서
1. Mã nguồn Server Socket
=======================
Server chỉ khởi động một luồng, vì vậy khi hiện thực chức năng đã sử dụng một số biến toàn cục.
1 int32_t srv_listen_fd{-1};
2 pthread_t srv_thread;
3 struct sockaddr_un srv_addr;
4 struct sockaddr_un cli_addr;
5 std::vector<int32_t> connect_fds;
void *server_socket_thread(void *arg)
{
SLOG_I("BẮT ĐẦU NHẬN - SERVER.");
// listen sockfd
int32_t ret = listen(srv_listen_fd, 1);
if(ret == -1)
{
SLOG_E("không thể lắng nghe yêu cầu kết nối từ client: %d - %s", errno, strerror(errno));
close(srv_listen_fd);
unlink(SOCK_PATH);
return NULL;
}
const char *connect_flag = "TestLeo";
while(1)
{
// accept client connect request
socklen_t len = sizeof(cli_addr);
int32_t connect_fd = accept(srv_listen_fd, (struct sockaddr*)(&cli_addr), &len);
if(connect_fd < 0)
{
SLOG_E("không thể chấp nhận yêu cầu kết nối từ client: %d - %s", errno, strerror(errno));
close(srv_listen_fd);
unlink(SOCK_PATH);
return NULL;
}
char buffer[64] = {0};
int32_t recv_size = 0;
recv_size = read(connect_fd, buffer, 10);
SLOG_I("CỔNG THÔNG TIN ĐỌC [%d] THÔNG TIN: %s", connect_fd, buffer);
if (0 == strncmp(buffer, connect_flag, 7))
{
connect_fds.push_back(connect_fd);
}
}
return NULL;
}
void socket_server_init()
{
int32_t ret;
SLOG_I("KHỞI ĐỘNG CỔNG THÔNG TIN BẮT ĐẦU[%s].", SOCK_PATH);
srv_listen_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if(srv_listen_fd < 0) {
SLOG_E("không thể tạo cổng thông tin giao tiếp: %d - %s", errno, strerror(errno));
return;
}
// set server address parameters
srv_addr.sun_family = AF_UNIX;
strcpy(srv_addr.sun_path, SOCK_PATH);
unlink(SOCK_PATH);
// bind sockfd và address
ret = bind(srv_listen_fd, (struct sockaddr*)&srv_addr, sizeof(srv_addr));
if(ret == -1) {
SLOG_E("không thể gắn cổng thông tin máy chủ[%s]: %d - %s", SOCK_PATH, errno, strerror(errno));
close(srv_listen_fd);
unlink(SOCK_PATH);
return;
}
// create server thread
if (EOK != pthread_create(&srv_thread, NULL, server_socket_thread, NULL)) {
SLOG_E("tạo luồng kết nối không thành công: %d - %s", errno, strerror(errno));
}
SLOG_I("KHỞI ĐỘNG CỔNG THÔNG TIN KẾT THÚC.");
}
2. Mã nguồn Client Socket
====================
Client dự định khởi động nhiều luồng (ví dụ: 30 luồng), vì vậy khi hiện thực client đã không sử dụng biến toàn cục và đảm bảo không phụ thuộc vào luồng.
void socket_client_init(int *status);
int send_connect_request(int socket_fd)
{
char request[] = "TestLeo";
SLOG_I("Gửi yêu cầu kết nối đến server.");
return write(socket_fd, request, sizeof(request));
}
void *receive_client_thread(void *arg)
{
if (NULL == arg)
{
SLOG_E("[receive_client_thread] tham số không được NULL.");
return NULL;
}
ReceiveModel *model = (ReceiveModel *)arg;
ssize_t recv_flag = 0;
unsigned char recv_buffer[64] = {0};
ssize_t data_length = 0;
SLOG_D("Tạo yêu cầu gửi dữ liệu.");
send_connect_request(model->socket);
SLOG_D("Tạo yêu cầu gửi dữ liệu kết thúc.");
while(true)
{
recv_flag = recv(model->socket, recv_buffer, sizeof(recv_buffer), 0);
if (0 == recv_flag)
{ // cần xem xét lại机制 kết nối
SLOG_E("[receive_client_thread] Kết nối từ server đã đóng.");
break;
}
else if (-1 == recv_flag)
{ // cần xem xét lại机制 kết nối
SLOG_E("[receive_client_thread]Recv không thành công. thông báo lỗi: %s", strerror(errno));
break;
}
data_length = recv_flag;
SLOG_D("NHẬN DỮ LIỆU (dлина: %d): %s", data_length, recv_buffer);
memset(recv_buffer, 0, sizeof(recv_buffer));
}
close(model->socket);
return NULL;
}
void *client_connection_thread(void *arg)
{
SLOG_I("[client_connection_thread] Trạng thái: 0x%x", arg);
if(NULL != arg) {
int *status = (int *)arg;
SLOG_I("[client_connection_thread] Trạng thái[%d]...", *status);
int connection_fd;
int connect_result;
int retry_count = 0;
static struct sockaddr_un srv_addr;
SLOG_I("Tạo cổng thông tin giao tiếp...");
connection_fd = socket(PF_UNIX, SOCK_STREAM, 0);
if(connection_fd < 0) {
SLOG_E("không thể tạo cổng thông tin giao tiếp.");
return NULL;
}
SLOG_D("Tạo cổng thông tin giao tiếp kết thúc.");
srv_addr.sun_family = AF_UNIX;
strcpy(srv_addr.sun_path, SOCK_PATH);
connect_result = connect(connection_fd, (struct sockaddr*)&srv_addr, sizeof(srv_addr));
SLOG_I("KẾT NỐI CỔNG THÔNG TIN KẾT THÚC: %d", connect_result);
while(-1 == connect_result) {
retry_count++;
SLOG_W("Kết nối đến server không thành công, lần thử第 %d", retry_count);
sleep(1);
connect_result = connect(connection_fd, (struct sockaddr*)&srv_addr, sizeof(srv_addr));
}
ReceiveModel model;
model.socket = connection_fd;
model.addr = &srv_addr;
pthread_t recv_thread;
if (pthread_create(&recv_thread, NULL, receive_client_thread, &model) != 0)
{
SLOG_E("tạo luồng nhận không thành công.");
}
else
{
pthread_join(recv_thread, NULL);
SLOG_W("luồng nhận đã kết thúc.");
}
}
}
void socket_client_init(int *status)
{
pthread_t connect_thread;
SLOG_I("* * * * * * * * * * * * * * * * * * [socket_client_init] bắt đầu [%d]...", *status);
if (EOK != pthread_create(&connect_thread, NULL, client_connection_thread, (void *)status))
{
SLOG_E("tạo luồng kết nối không thành công.");
}
}
3. Ví dụ mã nguồn gọi
========
Vì mã nguồn測試 được viết trong cùng một ứng dụng, nên sử dụng tham số dòng lệnh để phân biệt (chuyển tham số dòng lệnh thành biến kiểm soát: isSktFlag)
if(2 == isSktFlag) {
// client socket: kết nối đến server
for(int i = 0; i < 30; i++) {
SLOG_D("[cổng thông tin] bắt đầu client %d...", i);
socket_client_init(&i);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 1000)); // vì có các mã測試 khác sau này, nên thêm dòng này để延遲
}
else if(1 == isSktFlag) {
SLOG_D("[cổng thông tin] bắt đầu server...");
socket_server_init();
std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 1000)); // vì có các mã測試 khác sau này, nên thêm dòng này để延遲
}
Khi chỉ chạy Server, thông tin UDS được hiển thị như sau:
Sau khi chạy client, thông tin UDS được hiển thị như sau: