socket编程

网络编程

主要服务端进程,与客户端进程进行通信。客户端进程和服务端进程可以是在同一台主机上运行,也可以在不同的主机上运行,以下代码是在同一台主机上实现的

创建服务端

1. 功能:

用于处理客户端的连接请求和应答,具体的解释就是接收客户端发送msg,依据当前的客户端msg, 发送服务端的msg 到客户端

2. 过程:

创建监听套接字,用于监听客户端clientfd

 ser_fd = socket(AF_INET, SOCK_STREAM, 0);

accept()去接收客户端套接字,由于创建的监听套接字默认是block, accept都会阻塞等待客户端的连接,直到有连接建立并返回客户端套接字

int cli_fd = accept(ser_fd, NULL, NULL);

3.代码:

此处使用select io多路复用方式进行对客户端的监听

#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
#include <sys/time.h>
#include <unistd.h>
#include <netinet/in.h>
#include <string.h>
#include <poll.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>

#define SER_PORT 6000
#define BACKLOG 7
#define CLI_NUM 20
#define MAXLINE 2048

char buff[1024] = {0};
int main(int argc, char const *argv[])
{

    int ser_fd;
    struct sockaddr_in ser_addr, cli_addr;
    int cli_addr_len;
    int cli_fds[CLI_NUM] = {0};

    ser_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (ser_fd == -1)
    {
        perror("socket failed\n");
        return -1;
    }

    memset(&ser_addr, 0, sizeof(ser_addr));
    ser_addr.sin_family = AF_INET;
    ser_addr.sin_port = htons(SER_PORT);
    ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(ser_fd, (const struct sockaddr *)&ser_addr, sizeof(ser_addr)) < 0)
    {
        perror("bind error");
        return -1;
    }

    if (listen(ser_fd, BACKLOG) < 0)
    {
        perror("listen error");
        return -1;
    }
    #define FDS_MAX_NUM 1024
    fd_set rset, tmp;
    FD_ZERO(&rset);
    FD_SET(ser_fd, &rset);
    int maxfd = ser_fd;

    int cli[FDS_MAX_NUM];
    int i;
    for(i = 0; i < FDS_MAX_NUM; i++){
        cli[i] = -1;
    }
    struct timeval  timeout;
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;
    while(1){
        tmp = rset;
        int nready = select(maxfd + 1, &tmp, NULL, NULL, &timeout);
        
        if(FD_ISSET(ser_fd, &tmp)){
            
            int cli_fd = accept(ser_fd, NULL, NULL);
            if(cli_fd < 0){
                continue;
            }        
            printf("new connection \n");
            for(i = 0; i < FDS_MAX_NUM; i++){
                if(cli[i] == -1){
                    cli[i] = cli_fd;
                    FD_SET(cli_fd, &rset);
                    if(maxfd < cli_fd){
                        maxfd = cli_fd;
                    }
                    break;
                }
            }
            if(--nready == 0){  
                continue;
            }
        }

        for(i = 0; i < FDS_MAX_NUM; i++){
            char buf[1024] = {0};

            if(FD_ISSET(cli[i], &tmp)){
             
                int nbytes = recv(cli[i], buf, 1024, 0);
                if(nbytes == 0){
                    FD_CLR(cli[i], &rset);
                    close(cli[i]);
                    
                }else if(nbytes > 0){
                    printf("recv: %s\n", buf);
                }

            }
        }
        
    }


    
    return 0;
}

创建客户端

准确说是建立一个客户端进程

1. 功能

向服务端进程的发起连接请求,具体的解释是向服务端发送msg,同时可以接收服务端的msg, 通过服务端msg处理对应的业务逻辑

2. 过程

建立客户端套接字,

    int client_sock, ret;
    struct sockaddr_in server_address;
    client_sock = socket(AF_INET, SOCK_STREAM, 0);  //创建socketfd
    if (client_sock == -1)
    {
        perror("create client sock failed");
        exit(EXIT_FAILURE);
    }

    

使用connect()发起对服务端的连接请求

    ret = inet_pton(AF_INET, "192.168.126.128", &server_address.sin_addr.s_addr);  
    if (ret == -1)
    {
        perror("inet_pton error");
        exit(EXIT_FAILURE);
    }
    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(2048);
    ret = connect(client_sock, (struct sockaddr *)&server_address, sizeof(server_address));
    if (ret == -1)
    {
        perror("connect error");
        exit(EXIT_FAILURE);
    }
    while (1)  //可以通过 while循环不断向服务端进行msg 发送
    {
        printf("client: ");
        memset(buffer, 0, BUFFSIZ);
        fgets(buffer, BUFFSIZ, stdin);
        write(client_sock, buffer, BUFFSIZ);
    }

3. 代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#define BUFFSIZ 1024

char buffer[BUFFSIZ];
int main(int argc, char const *argv[])
{

    int client_sock, ret;
    struct sockaddr_in server_address;
    client_sock = socket(AF_INET, SOCK_STREAM, 0);
    if (client_sock == -1)
    {
        perror("create client sock failed");
        exit(EXIT_FAILURE);
    }

    ret = inet_pton(AF_INET, "192.168.126.128", &server_address.sin_addr.s_addr);
    if (ret == -1)
    {
        perror("inet_pton error");
        exit(EXIT_FAILURE);
    }
    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(2048);

    ret = connect(client_sock, (struct sockaddr *)&server_address, sizeof(server_address));
    if (ret == -1)
    {
        perror("connect error");
        exit(EXIT_FAILURE);
    }
    while (1)
    {
        printf("client: ");
        memset(buffer, 0, BUFFSIZ);
        fgets(buffer, BUFFSIZ, stdin);
        write(client_sock, buffer, BUFFSIZ);
    }

    return 0;
}

学习链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值