现在的位置: 首页 > 综合 > 正文

Linux网络编程:TCP服务器(多进程)

2013年10月18日 ⁄ 综合 ⁄ 共 4894字 ⁄ 字号 评论关闭

服务器程序:tcp_server.c

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <linux/in.h>
#include <signal.h>

extern void sig_proccess(int signo);

#define BACKLOG 5               /* 侦听队列长度 */

/*************************************************
* Function    : 
* Description : 服务端主程序
* Calls       : process_conn_server
* Called By   : 
* Input       : 
* Output      : 
* Return      : 
*************************************************/
int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        printf("Usage:%s port_number\n", argv[0]);
        return 1;
    }

    int port;
    int ss, sc;                 /* ss为服务器的socket描述符,sc为客户端的socket描述符 */
    struct sockaddr_in server_addr; /* 服务器地址结构 */
    struct sockaddr_in client_addr; /* 客户端地址结构 */
    int err;                    /* 返回值 */
    pid_t pid;                  /* 分叉的进行id */

    signal(SIGINT, sig_proccess);
    signal(SIGPIPE, sig_proccess);

    /* 建立一个流式套接字 */
    ss = socket(AF_INET, SOCK_STREAM, 0);
    if (ss < 0)
    {                           /* 出错 */
        printf("socket error\n");
        return -1;
    }
    //获得输入的端口 
    port = atoi(argv[1]);

    /* 设置服务器地址 */
    bzero(&server_addr, sizeof(server_addr));   /* 清0 */
    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 (;;)
    {
        int addrlen = sizeof(struct sockaddr);
        /* 接收客户端连接 */
        sc = accept(ss, (struct sockaddr *)&client_addr, &addrlen);
        if (sc < 0)
        {                       /* 出错 */
            continue;           /* 结束本次循环 */
        }

        /* 建立一个新的进程处理到来的连接 */
        pid = fork();           /* 分叉进程 */
        if (pid == 0)
        {                       /* 子进程中 */
            close(ss);          /* 在子进程中关闭服务器的侦听 */
            process_conn_server(sc);    /* 处理连接 */
        }
        else
        {
            close(sc);          /* 在父进程中关闭客户端的连接 */
        }
    }
}

客户端程序:tcp_client.c

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <linux/in.h>
#include <signal.h>

extern void sig_proccess(int signo);
extern void sig_pipe(int signo);
static int s;
void sig_proccess_client(int signo)
{
    printf("Catch a exit signal\n");
    close(s);
    exit(0);
}

/*************************************************
* Function    : 
* Description : 客户端主程序
* Calls       : process_conn_client
* Called By   : 
* Input       : 
* Output      : 
* Return      : 
*************************************************/
int main(int argc, char *argv[])
{
    int port;
    struct sockaddr_in server_addr; /* 服务器地址结构 */
    int err;                    /* 返回值 */

    signal(SIGINT, sig_proccess);
    signal(SIGPIPE, sig_pipe);

    /* 建立一个流式套接字 */
    s = socket(AF_INET, SOCK_STREAM, 0);
    if (s < 0)
    {                           /* 出错 */
        printf("socket error\n");
        return -1;
    }

    /* 将用户输入的字符串类型的IP地址转为整型 */
    inet_pton(AF_INET, argv[1], &server_addr.sin_addr);
    port = atoi(argv[2]);

    /* 设置服务器地址 */
    bzero(&server_addr, sizeof(server_addr));   /* 清0 */
    server_addr.sin_family = AF_INET;   /* 协议族 */
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);    /* 本地地址 */
    server_addr.sin_port = htons(port); /* 服务器端口 */

    /* 连接服务器 */
    connect(s, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
    process_conn_client(s);     /* 客户端处理过程 */
    close(s);                   /* 关闭连接 */
}

调用程序:tcp_process.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>

/*************************************************
* Function    : 
* Description : 服务器对客户端的处理
* Calls       : 
* Called By   : 
* Input       : 
* Output      : 
* Return      : 
*************************************************/
void process_conn_server(int s)
{
    ssize_t size = 0;
    char buffer[1024];          /* 数据的缓冲区 */

    for (;;)
    {                           /* 循环处理过程 */
        /* 从套接字中读取数据放到缓冲区buffer中 */
        memset(buffer, '0', 1024);
        size = read(s, buffer, 1024);
        if (size == 0)
        {                       /* 没有数据 */
            return;
        }
        printf("Server: Client had sent %.2d bytes to me!\n", size - 1);

        /* 构建响应字符,为接收到客户端字节的数量 */
        memset(buffer, '0', 1024);
        sprintf(buffer, "Client: Server had received %.2d bytes from me!\n", size - 1);
        write(s, buffer, strlen(buffer) + 1);   /* 发给客户端 */
    }
}

/*************************************************
* Function    : 
* Description : 客户端的处理过程
* Calls       : 
* Called By   : 
* Input       : 
* Output      : 
* Return      : 
*************************************************/
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); /* 写到标准输出 */
        }
    }
}

/*************************************************
* Function    : 
* Description : 
* Calls       : 
* Called By   : tcp_server.c tcp_client.c
* Input       : 
* Output      : 
* Return      : 
*************************************************/
void sig_proccess(int signo)
{
    printf("Catch a exit signal\n");
    exit(0);
}

/*************************************************
* Function    : 
* Description : 
* Calls       : 
* Called By   : tcp_server.c tcp_client.c
* Input       : 
* Output      : 
* Return      : 
*************************************************/
void sig_pipe(int sign)
{
    printf("Catch a SIGPIPE signal\n");
}

makefile文件:

CC = gcc
all:client server
	
client:tcp_process.o tcp_client.o
	$(CC) -o client tcp_process.o tcp_client.o
server:tcp_process.o tcp_server.o
	$(CC) -o server tcp_process.o tcp_server.o
clean:
	rm -f client server *.o

测试结果:

[root@ShiGuang songjingbing]# ./server 8080
Server: Client had sent 11 bytes to me!
Server: Client had sent 11 bytes to me!
Server: Client had sent 41 bytes to me!

[root@ShiGuang songjingbing]# ./client 192.168.1.123 8080
fsafdsafsaf
Client: Server had received 11 bytes from me!
dfasfdsafsa
Client: Server had received 11 bytes from me!
ddddddddddddddddddddddddddddddddddddddddd
Client: Server had received 41 bytes from me!

抱歉!评论已关闭.