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;
}
相关推荐
chlk1232 小时前
Linux文件权限完全图解:读懂 ls -l 和 chmod 755 背后的秘密
linux·操作系统
舒一笑2 小时前
Ubuntu系统安装CodeX出现问题
linux·后端
改一下配置文件3 小时前
Ubuntu24.04安装NVIDIA驱动完整指南(含Secure Boot解决方案)
linux
深紫色的三北六号12 小时前
Linux 服务器磁盘扩容与目录迁移:rsync + bind mount 实现服务无感迁移(无需修改配置)
linux·扩容·服务迁移
SudosuBash16 小时前
[CS:APP 3e] 关于对 第 12 章 读/写者的一点思考和题解 (作业 12.19,12.20,12.21)
linux·并发·操作系统(os)
哈基咪怎么可能是AI1 天前
为什么我就想要「线性历史 + Signed Commits」GitHub 却把我当猴耍 🤬🎙️
linux·github
十日十行2 天前
Linux和window共享文件夹
linux
木心月转码ing2 天前
WSL+Cpp开发环境配置
linux
崔小汤呀3 天前
最全的docker安装笔记,包含CentOS和Ubuntu
linux·后端
何中应3 天前
vi编辑器使用
linux·后端·操作系统