使用socket+多线程建立通信连接.c

/* 使用socket建立通信连接,使连接双方可自由收发数据
 * 客户端代码
 */
#include <sys/un.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <netinet/in.h>
#include <arpa/inet.h>

 #define PORT 8000

# define IP "127.0.0.1" //本地还回IP用时修改

 void* Write (void* tmp) //写线程,void*是线程创建的标准参数,用时修改
 {    
     int* fd = (int*)tmp; //类型转换
     char buf[128];
     int ret;

     while (1){
    fgets(buf, sizeof(buf), stdin); //从键盘中读取数据
    if (strcmp(buf,"quit\n") ==0){
        pthread_exit(NULL);//退出线程
    }
    ret = write(*fd, buf, strlen(buf)+1); //将数据写进客户端套接字
    
    if (ret < 0) {
        perror("write error.");
        exit(1);
    } else if (ret == 0) {
        printf("do not write data.\n");
        continue ;
    }
  }
}
void* Read (void* tmp){ //读线程,当有数据过来时可以无阻塞读取
    char buf[128];
    int ret;
    int* fd = (int*)tmp;

    while(1){
    ret = read(*fd, buf, sizeof(buf));//从套接字中读取数据
    if (ret < 0) {
        perror("read error.\n");
        exit(1);
    } else if (ret == 0) {
        printf("服务器已关闭.\n");
        exit(0);
    } else {
        printf("had received: \033[31m%s\033[0m\n", buf);
    }
    }
}
//主函数
int main(void) {
    int fd;
    struct sockaddr_in addr_server;
    int ret;
    //1. 创建套接字

    fd = socket(AF_INET, SOCK_STREAM, 0); //参数1:网络通信 参数2:数据stream 参数3:默认协议
    if (fd < 0) {
        perror("socket error.");
        exit(1);
    }

    //2. 设置服务器地址
    addr_server.sin_family = AF_INET;
    addr_server.sin_addr.s_addr = inet_addr(IP);
    addr_server.sin_port = htons(PORT);//htos 小端转大端

    //3. 向服务器发起连接

    ret = connect(fd, (struct sockaddr*)&addr_server, sizeof(addr_server));
    if (ret < 0) {
        perror("connect error.");
        exit(1);
    }

    printf("已经连接到服务器.\n");

        pthread_t pthread_id3;
        pthread_t pthread_id4;
        ret = pthread_create (&pthread_id3  ,NULL    ,Write    ,&fd); //写线程
        ret = pthread_create (&pthread_id4  ,NULL    ,Read    ,&fd); //读线程
        pthread_join(pthread_id3,NULL);//等待写线程结束,如果写quit将退出整个客户端
    return 0;
}

/* 使用socket建立通信连接,使连接双方可自由收发数据
 * 服务器端代码
 */
#include <sys/un.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <netinet/in.h>
#include <arpa/inet.h>

# define PORT 8000

 int ret ;
 char* info;
 char buf[256];

void* Read(void* tmp) { //读线程
    int* client_fd = (int*) tmp;

    while (1) {
        ret = read(*client_fd, buf, sizeof(buf));//从套接字中读数据
        if (ret < 0) {
            perror("read error.");
            pthread_exit(info);
        } else if (ret == 0) {
            //该客户端关闭后,返回0
            printf("客户端已关闭.\n");
            pthread_exit(info);
        } else {
            printf("server read:\033[31m%s\033[0m\n", buf);
            char *p = (char*)buf;
 //将小写字母转为大写字母
     while (*p) {
        if (*p >= 'a' && *p <= 'z') {
            *p += 'A' - 'a';
        }
            p++;
        }
        }
        ret = write(*client_fd, buf, strlen(buf)+1);
        if (ret < 0) {
            perror("write error.");
            pthread_exit(info);
        } else if (ret == 0) {
            printf("do not write data.\n");
            pthread_exit(info);
        }    
}
  }
 void* Write(void* tmp) { //写线程
     char buf[128];
     int* client_fd = (int*) tmp;
     while(1){
    fgets(buf,sizeof(buf),stdin);
    ret = write(*client_fd, buf, strlen(buf)+1);
        if (ret < 0) {
            perror("write error.");
            pthread_exit(info);
        } else if (ret == 0) {
            printf("do not write data.\n");
            pthread_exit(info);
        }
    }
}
void* handle (void* data){  //pthread_create传参必须是void* 类型
    int* client_fd = (int*) data; //强制转换
    char buf[128];
    printf ("客户端%d已经连接\n",*client_fd);

        int fd = *client_fd;
        pthread_t pthread_id3;
        pthread_t pthread_id4;
        ret = pthread_create (&pthread_id3  ,NULL    ,Read    ,client_fd);
        ret = pthread_create (&pthread_id4  ,NULL    ,Write    ,client_fd);



        //把处理结果发送给客户端
       
    }


int  main(void) {
    int server_fd;
    int client_fd;
    int ret;
    pthread_t pthread_id1;
    //服务器地址

    struct sockaddr_in addr_server;
    struct sockaddr_in addr_client;

    socklen_t addr_len = sizeof(addr_client);
    server_fd = socket(AF_INET,  SOCK_STREAM,  0);           

    if (server_fd < 0) {
        perror("socket error.");
        exit(1);
    }

    //3. 设置服务器地址

    addr_server.sin_family = AF_INET;
    addr_server.sin_addr.s_addr = INADDR_ANY;
    addr_server.sin_port = htons(PORT);

    //4. 绑定套接字
    ret = bind(server_fd, (struct sockaddr*)&addr_server,sizeof(addr_server));
    if (ret < 0) {
        perror("bind error.");
        exit(1);
    }

    //5. 创建套接字队列

    listen(server_fd, 20);

    //6. 循环处理客户端的请求
    while(1){
        printf("正在等待客户端接入...\n");
        client_fd = accept(server_fd, (struct sockaddr*)&addr_client, &addr_len);
        printf("客户端%d已经接入.\n",client_fd);

        ret = pthread_create (&pthread_id1  ,NULL    ,handle     ,&client_fd);
        {
        if (ret != 0 ){
            perror ("pthread_create failed !\n");
            exit(0);
        }
        }
    }

    while(1); //服务器未设置退出
    return 0;
}
//多线程解决读写交替阻塞的问题
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值