socket

1.socket是一个常用的网络通信API,今天就学习一下多线程配合socket进行通信。

服务端server.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>

#define SERVERPORT     9009
#define BACKLOG     10
#define HI "success!\n"
#define END "end"
static int server_fd = -1, client_fd = -1;

static void *create_server(void)
{
    int ret = -1;
    struct sockaddr_in server_addr = {0}, client_addr = {0};
    socklen_t sock_len = 0;
    char recv_buf[128] = {0};

    server_fd = socket(AF_INET, SOCK_STREAM, 0);  //创建socket句柄
    if(server_fd < 0)
    {
        perror("socket");
        return NULL;
    }

    server_addr.sin_family = AF_INET;            //设置ipv4协议
    server_addr.sin_port = htons(SERVERPORT);    //设置端口
    server_addr.sin_addr.s_addr = INADDR_ANY;    //设置ip地址为本机地址

    ret = bind(server_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in));  //绑定地址
    if(ret == -1)
    {
        perror("server bind");
        return NULL;
    }

    ret = listen(server_fd, BACKLOG);         //监听地址
    if (ret < 0)
    {
        perror("listen");
        return NULL;
    }

    client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &sock_len);  //等待服务端连接
    printf("client connected, fd = %d\n", client_fd);

    while(1)
    {
        ret = send(client_fd, HI, sizeof(HI), 0);                //发送success给客户端
        printf("send to client msg length = %d\n", ret);
        ret = recv(client_fd, &recv_buf, sizeof(recv_buf), 0);   //接收客户端传递的消息
        printf("recv from client msg: %s\n", recv_buf);
        if(strncmp(END, recv_buf, sizeof(END)) == 0)             //接收到end,结束通信
        {
            ret = send(client_fd, recv_buf, strlen(recv_buf), 0);
            printf("server exited, send last msg to client length = %d\n",ret);
            return NULL;
        }
        memset(recv_buf, 0, sizeof(recv_buf));
    }
    return NULL;
}

int main(int argc, char const *argv[])
{
    int ret = -1;
    pthread_t pt = -1;
    ret = pthread_create(&pt, NULL, (void *)create_server, NULL);  //创建子线程
    if(ret != 0)
    {
        perror("pthread_create");
        goto out;
    }

    ret = pthread_join(pt, NULL);     //等待线程结束
    if(ret != 0)
    {
        perror("pthread_join");
    }

out:
    if(server_fd != -1) close(server_fd);    //释放资源
    if(client_fd != -1) close(client_fd);
    return 0;
}

客户端client.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>

#define SERVERPORT     9009
#define END "end"
static int client_fd = -1;

static int init(void)
{
    int ret = -1;
    struct sockaddr_in client_addr = {0};

    client_fd = socket(AF_INET, SOCK_STREAM, 0);   //创建socket句柄
    if(client_fd < 0)
    {
        perror("socket");
        return -1;
    }
    client_addr.sin_family = AF_INET;            //和服务端一毛一样
    client_addr.sin_port = htons(SERVERPORT);
    client_addr.sin_addr.s_addr = INADDR_ANY;

    ret = connect(client_fd, (struct sockaddr *)&client_addr, sizeof(struct sockaddr_in));  //连接到服务端
    if(ret == -1)
    {
        perror("connect");
        return -1;
    }
    return 0;
}

static void *recv_thread(void)
{
    int ret = -1;
    char recv_buf[128] = {0};
    while(1)
    {
        ret = recv(client_fd, &recv_buf, sizeof(recv_buf), 0);   //接收服务端发过来的success信息
        printf("recv from server: %s\n", recv_buf);
        if(strncmp(END, recv_buf, sizeof(END)) == 0)      //收到end结束子线程
        {
            printf("client exited!\n");
            return NULL;
        }
        memset(recv_buf, 0, sizeof(recv_buf));
    }
    return NULL;
}

static void *intput_thread(void)
{
    char input_buf[128] = {0};
    int ret = -1;
    while(1)
    {
        scanf("%s", input_buf);          //键盘输入
        ret = send(client_fd, input_buf, strlen(input_buf), 0);  //发送键盘输入的信息
        printf("intput_thread send to server msg length = %d\n", ret);
        if(strncmp(END, input_buf, sizeof(END)) == 0)    //输入end结束子线程
        {
            printf("intput_thread exited!\n");
            return NULL;
        }
        memset(input_buf, 0, sizeof(input_buf));
    }
    return NULL;
}

int main(int argc, char const *argv[])
{
    int ret = -1;
    pthread_t pt1 = -1, pt2 = -1;
    if(init())
    {
        return -1;
    }
    ret = pthread_create(&pt1, NULL, (void *)recv_thread, NULL);
    if(ret != 0)
    {
        perror("pthread_create");
        goto out;
    }

    ret = pthread_create(&pt2, NULL, (void *)intput_thread, NULL);
    if(ret != 0)
    {
        perror("pthread_create");
        goto out;
    }

    ret = pthread_join(pt1, NULL);
    if(ret != 0)
    {
        perror("pthread_join pt1");
    }

    ret = pthread_join(pt2, NULL);
    if(ret != 0)
    {
        perror("pthread_join pt2");
    }

out:
    if(client_fd != -1) close(client_fd);
    return 0;
}

简单Makefile进行编译

all:
	gcc client.c -o client -pthread
	gcc server.c -o server -pthread

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值