Linux TCP 服务器实现双向通信1v1

客户端

cpp 复制代码
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>

char buf[250];
ssize_t recv_data;

// 执行线程的函数
void* TX(void* arg) {
    int socket_ret = *((int*)arg);
    while (1) {
        memset(buf, 0, sizeof(buf));
        recv_data = recv(socket_ret, buf, sizeof(buf) - 1, 0);
        if (recv_data > 0) {
            printf("客户端发来:%s\n", buf);
        } else {
            // 处理接收数据结束或错误
            break;
        }
    }
    // 关闭客户端套接字
    close(socket_ret);
    return NULL;
}

void* RX(void* arg) {
    int socket_ret = *((int*)arg);
    while (1) {
		 printf("发送给客户端:");
        memset(buf, 0, sizeof(buf));
		fgets(buf,sizeof(buf),stdin);
        recv_data = send(socket_ret, buf, sizeof(buf) - 1, 0);
        if (recv_data > 0) {
            printf("发送成功\n");
        } else {
             printf("发送失败\n");
            break;
        }
    }
    // 关闭客户端套接字
    close(socket_ret);
    return NULL;
}
int main(int argc, char *argv[]){
    if(argc != 3){
        fprintf(stderr, "Usage: %s <IP> <Port>\n", argv[0]); // 修正:提供完整的错误信息
        exit(EXIT_FAILURE);
    }
	pthread_t thread_TX, thread_RX;

    struct sockaddr_in my_addr, oth_addr;


    int socket_ret = socket(AF_INET, SOCK_STREAM, 0);
    if(socket_ret < 0){
        perror("socket"); // 修正:提供完整的错误信息
        exit(EXIT_FAILURE);
    }

    memset(&my_addr, 0, sizeof(my_addr)); // 修正:使用memset替代bzero
    my_addr.sin_family = AF_INET;
    my_addr.sin_port = htons(atoi(argv[2])); // 注意:如果atoi(argv[2])结果过大,可能会溢出
    my_addr.sin_addr.s_addr = inet_addr(argv[1]); // 注意:如果argv[1]不是有效的IP地址,这里会返回INADDR_NONE

	int connect_ret = connect(socket_ret, (const struct sockaddr *)&my_addr, sizeof(my_addr));
	if (connect_ret < 0)
	{
		perror("connect");
		exit(1);
	}


    while(1){
		//线程
        int result_TX = pthread_create(&thread_TX, NULL, TX, (void*)&socket_ret);
        if (result_TX != 0) {
            perror("pthread_create for TX");
            close(socket_ret);
            continue;
        }

        int result_RX = pthread_create(&thread_RX, NULL, RX, (void*)&socket_ret);
        if (result_RX != 0) {
            perror("pthread_create for RX");
            close(socket_ret);
            pthread_join(thread_TX, NULL); // 等待TX线程结束
            continue;
        }

        // 等待两个线程结束
        pthread_join(thread_TX, NULL);
        pthread_join(thread_RX, NULL);

        // 关闭客户端套接字
        close(socket_ret);
   

		}
		

    


    return 0;
}

服务器

cpp 复制代码
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>

char buf[250];
ssize_t recv_data;

// 执行线程的函数
void* TX(void* arg) {
    int client_socket = *((int*)arg);
    while (1) {
        memset(buf, 0, sizeof(buf));
        recv_data = recv(client_socket, buf, sizeof(buf) - 1, 0);
        if (recv_data > 0) {
            printf("客户端发来:%s\n", buf);
        } else {
            // 处理接收数据结束或错误
            break;
        }
    }
    // 关闭客户端套接字
    close(client_socket);
    return NULL;
}

void* RX(void* arg) {
    int client_socket = *((int*)arg);
    while (1) {
		 printf("发送给客户端:");
        memset(buf, 0, sizeof(buf));
		fgets(buf,sizeof(buf),stdin);
        recv_data = send(client_socket, buf, sizeof(buf) - 1, 0);
        if (recv_data > 0) {
            printf("发送成功\n");
        } else {
             printf("发送失败\n");
            break;
        }
    }
    // 关闭客户端套接字
    close(client_socket);
    return NULL;
}

int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <IP> <Port>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    int socket_ret = socket(AF_INET, SOCK_STREAM, 0);
    if (socket_ret < 0) {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    struct sockaddr_in my_addr, oth_addr;
	
    memset(&my_addr, 0, sizeof(my_addr));
    my_addr.sin_family = AF_INET;
    my_addr.sin_port = htons(atoi(argv[2]));
    my_addr.sin_addr.s_addr = inet_addr(argv[1]);

    if (bind(socket_ret, (const struct sockaddr *)&my_addr, sizeof(my_addr)) < 0) {
        perror("bind");
        exit(EXIT_FAILURE);
    }

    if (listen(socket_ret, 10) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    socklen_t len = sizeof(oth_addr);
    pthread_t thread_TX, thread_RX;

    while (1) {
        int client_socket = accept(socket_ret, (struct sockaddr *)&oth_addr, &len);
        if (client_socket < 0) {
            perror("accept");
            continue;
        }
		//线程
        int result_TX = pthread_create(&thread_TX, NULL, TX, (void*)&client_socket);
        if (result_TX != 0) {
            perror("pthread_create for TX");
            close(client_socket);
            continue;
        }

        int result_RX = pthread_create(&thread_RX, NULL, RX, (void*)&client_socket);
        if (result_RX != 0) {
            perror("pthread_create for RX");
            close(client_socket);
            pthread_join(thread_TX, NULL); // 等待TX线程结束
            continue;
        }

        // 等待两个线程结束
        pthread_join(thread_TX, NULL);
        pthread_join(thread_RX, NULL);

        // 关闭客户端套接字
        close(client_socket);
    }

    // 关闭服务器套接字
    close(socket_ret);
    return 0;
}
相关推荐
Ruiery8 小时前
Linux 6.6内核 CPU 深度解析(七):调度器启动 — 从单核到多核,调度器分阶段点亮
linux·运维·服务器
50万马克的面包8 小时前
CSDN-栈队列数组-知识点整理
linux·运维·服务器
wjkjpcba9 小时前
PCBA烧录程序是什么:PCBA包工包料厂家解析烧录与测试
linux·数据库·人工智能·smt贴片加工·pcba贴片加工厂
꯭自꯭闭꯭10 小时前
达梦事物特性及MVCC
linux·运维·数据库
羔羊++11 小时前
18_实验十七_其他命令与自定义启动变量
linux
DYWorker00113 小时前
Linux驱动:RK3568 GMAC + YT8531C 千兆以太网全流程解剖
linux
lisanmengmeng15 小时前
NRPE 添加命令(一)
linux·运维·服务器
树下水月16 小时前
Typora破解
linux·服务器·前端
沫璃染墨16 小时前
《从零入门Linux系统篇(五十七):线程篇·十——生产者消费者模型进阶:从环形缓冲区到POSIX信号量》
linux·运维·服务器·开发语言·c++·系统架构·信号处理
wuminyu16 小时前
LockStack在虚拟线程Mount和Unmount拷贝过程剖析
java·linux·c语言·jvm·c++