Linux下C语言实现简单的套接字编程

文章最后更新时间为:2019年04月11日 14:27:27

一篇水水的文章,仅记录用。

0x01 服务端 tcp_server.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PORT 9999  /*侦听端口地址*/
#define BACKLOG 2  /*侦听队列长度*/

/*服务器对客户端的处理*/
void process_conn_server(int s)
{
    ssize_t size = 0;
    char buffer_recv[1024];  /*数据的缓冲区*/
    char buffer_send[1024];
    for(;;){  /*循环处理过程*/        
        size = read(s, buffer_recv, 1024);  /*从套接字中读取数据放到缓冲区buffer中*/
        if(size == 0){  /*没有数据*/
            return;
        }
        /*构建响应字符,为接收到客户端字节的数量*/
        sprintf(buffer_send, "%d bytes altogether:%s\n", size, buffer_recv);
        write(s, buffer_send, strlen(buffer_send)+1);/*发给客户端*/
    }
    
}

int main(int argc, char *argv[])
{
    int ss,sc;  /*ss为服务器的socket描述符,sc为客户端的socket描述符*/
    struct sockaddr_in server_addr;  /*服务器地址结构*/
    struct sockaddr_in client_addr;  /*客户端地址结构*/
    int err;  /*返回值*/
    pid_t pid;  /*分叉的进行ID*/

    /*建立一个流式套接字*/
    ss = socket(AF_INET, SOCK_STREAM, 0);
    if(ss < 0){  /*出错*/
        printf("socket error\n");
        return -1;
    }
    
    /*设置服务器地址*/
    bzero(&server_addr, sizeof(server_addr));  /*清零*/
    server_addr.sin_family = AF_INET;  /*协议族*/
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);  /*本地地址*/
    server_addr.sin_port = htons(PORT);  /*服务器端口*/
    
    /*绑定地址结构到套接字描述符*/
    err = bind(ss, (struct sockaddr*)&server_addr, sizeof(server_addr));
    if(err < 0){/*出错*/
        printf("bind error\n");
        return -1;    
    }
    
    /*设置侦听*/
    err = listen(ss, BACKLOG);
    if(err < 0){  /*出错*/
        printf("listen error\n");
        return -1;
    }
    
        /*主循环过程*/
    for(;;)    {
        socklen_t addrlen = sizeof(struct sockaddr);
        
        sc = accept(ss, (struct sockaddr*)&client_addr, &addrlen); 
        /*接收客户端连接*/
        if(sc < 0){  /*出错*/
            continue;  /*结束本次循环*/
        }    
        
        /*建立一个新的进程处理到来的连接*/
        pid = fork();  /*分叉进程*/
        if( pid == 0 ){  /*子进程中*/
            process_conn_server(sc);  /*处理连接*/
            close(ss);  /*在子进程中关闭服务器的侦听*/
        }else{
            close(sc);  /*在父进程中关闭客户端的连接*/
        }
    }
}

0x02 客户端 tcp_client.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PORT 9999  /*侦听端口地址*/

/*客户端的处理过程*/
void process_conn_client(int s)
{
    ssize_t size = 0;
    char buffer[1024];  /*数据的缓冲区*/

    for(;;){  /*循环处理过程*/
        /*从标准输入中读取数据放到缓冲区buffer中*/
        size = read(0, buffer, 1024);
        if(size > 0){  /*读到数据*/
            write(s, buffer, size);  /*发送给服务器*/
            size = read(s, buffer, 1024);  /*从服务器读取数据*/
            write(1, buffer, size);  /*写到标准输出*/
        }
    }    
}

int main(int argc, char *argv[])
{
    int s;  /*s为socket描述符*/
    struct sockaddr_in server_addr;  /*服务器地址结构*/
    if(argc<2) {
        printf("Usage ./client server-addr\n");
        return 0;
    }
    s = socket(AF_INET, SOCK_STREAM, 0);  /*建立一个流式套接字 */
    if(s < 0){  /*出错*/
        printf("socket error\n");
        return -1;
    }    
    
    /*设置服务器地址*/
    bzero(&server_addr, sizeof(server_addr));  /*清零*/
    server_addr.sin_family = AF_INET;  /*协议族*/
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);  /*本地地址*/
    server_addr.sin_port = htons(PORT);  /*服务器端口*/
    
    /*将用户输入的字符串类型的IP地址转为整型*/
    inet_pton(AF_INET, argv[1], &server_addr.sin_addr);    
    /*连接服务器*/
    connect(s, (struct sockaddr*)&server_addr, sizeof(struct sockaddr));
    process_conn_client(s);  /*客户端处理过程*/
    close(s);  /*关闭连接*/
    return 0;
}

0x03 结果

编译一下:

gcc tcp_server.c -o server
gcc tcp_client.c -o client

运行结果:

1 + 8 =
快来做第一个评论的人吧~