111

//TCP server:

#include <stdio.h>

#include <stdlib.h>

#include <strings.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <memory.h>

#include <unistd.h>

//#include <linux/in.h>

#include <netinet/in.h>

//#include <linux/inet_diag.h>

#include <arpa/inet.h>

#include <signal.h>

/**

  关于 sockaddr  sockaddr_in  socketaddr_un说明

  http://maomaozaoyue.blog.sohu.com/197538359.html

  */

#define PORT    11910   //定义通信端口

#define BACKLOG 5       //定义侦听队列长度

#define buflen  1024

void process_conn_server(int s);

void sig_pipe(int signo);

int ss,sc;  //ss为服务器socket描述符,sc为某一客户端通信socket描述符

int main(int argc,char *argv[])

{

    struct sockaddr_in server_addr; //存储服务器端socket地址结构

    struct sockaddr_in client_addr; //存储客户端 socket地址结构

    int err;    //返回值

    pid_t pid;  //分叉进行的ID

     ss = socket(AF_INET,SOCK_STREAM,0); //建立一个序列化的,可靠的,双向连接的的字节流

    if(ss<0)

    {

        printf("server : server socket create error\n");

        return -1;

    }

     sighandler_t ret;

    ret = signal(SIGTSTP,sig_pipe);

    if(SIG_ERR == ret)

    {

        printf("信号挂接失败\n");

        return -1;

    }

    else

        printf("信号挂接成功\n");

    memset(&server_addr,0,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(sockaddr));

    if(err<0)

    {

        printf("server : bind error\n");

        return -1;

    }

    err = listen(ss,BACKLOG);   //设置监听的队列大小

    if(err < 0)

    {

        printf("server : listen error\n");

        return -1;

    }

    for(;;)

    {

        socklen_t addrlen = sizeof(client_addr);

        //accept返回客户端套接字描述符

        sc = accept(ss,(struct sockaddr *)&client_addr,&addrlen);  //注,此处为了获取返回值使用 指针做参数

        if(sc < 0)  //出错

        {

            continue;   //结束此次循环

        }

        else

        {

            printf("server : connected\n");

        }

        pid = fork();

        //fork 调用说明:子进程返回 0 ;父进程返回子进程 ID

        if(pid == 0)        //子进程,与客户端通信

        {

            close(ss);

            process_conn_server(sc);

        }

        else

        {

            close(sc);

        }

    }

}

//通过套接字 s 与客户端进行通信

void process_conn_server(int s)

{

    ssize_t size = 0;

    char buffer[buflen];  //定义数据缓冲区

    for(;;)

    {

        //等待读

        for(size = 0;size == 0 ;size = read(s,buffer,buflen));

        //输出从客户端接收到的数据

        printf("%s",buffer);

 

        //结束处理

        if(strcmp(buffer,"quit") == 0)

        {

            close(s);   //成功返回0,失败返回-1

            return ;

        }

        sprintf(buffer,"%d bytes altogether\n",size);

        write(s,buffer,strlen(buffer)+1);

    }

}

void sig_pipe(int signo)

{

    printf("catch a signal\n");

    if(signo == SIGTSTP)

    {

        printf("接收到 SIGTSTP 信号\n");

        int ret1 = close(ss);

        int ret2 = close(sc);

        int ret = ret1>ret2?ret1:ret2;

        if(ret == 0)

            printf("成功 : 关闭套接字\n");

        else if(ret ==-1 )

            printf("失败 : 未关闭套接字\n");

 

        exit(1);

    }

}

 

//TCP client

#include <stdio.h>

#include <strings.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <stdlib.h>

#include <memory.h>

#include <arpa/inet.h>

#include <netinet/in.h>

#include <signal.h> //添加信号处理  防止向已断开的连接通信

#define PORT    11910

#define Buflen  1024

void process_conn_client(int s);

void sig_pipe(int signo);    //用户注册的信号函数,接收的是信号值

int s;  //全局变量 , 存储套接字描述符

int main(int argc,char *argv[])

{

    sockaddr_in server_addr;

    int err;

    sighandler_t ret;

    char server_ip[50] = "";

    s= socket(AF_INET,SOCK_STREAM,0);

    if(s<0)

    {

        printf("client : create socket error\n");

        return 1;

    }

    ret = signal(SIGTSTP,sig_pipe);

    if(SIG_ERR == ret)

    {

        printf("信号挂接失败\n");

        return -1;

    }

    else

        printf("信号挂接成功\n") ;

    memset(&server_addr,0,sizeof(server_addr));

    server_addr.sin_family = AF_INET;

    server_addr.sin_port = htons(PORT);

    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    printf("please input server ip address : \n");

    read(0,server_ip,50);

    //err = inet_pton(AF_INET,server_ip,&server_addr.sin_addr.s_addr);

    server_addr.sin_addr.s_addr = inet_addr(server_ip);

    err = connect(s,(struct sockaddr *)&server_addr,sizeof(sockaddr));

    if(err == 0)

    {

        printf("client : connect to server\n");

    }

    else

    {

        printf("client : connect error\n");

        return -1;

    }

    //与服务器端进行通信

    process_conn_client(s);

    close(s);

}

void process_conn_client(int s)

{

    ssize_t size = 0;

    char buffer[Buflen];

    for(;;)

    {

        memset(buffer,'\0',Buflen);

        /*从标准输入中读取数据放到缓冲区buffer中*/

        size = read(0,buffer,Buflen);   // 0,被默认的分配到标准输入  1,标准输出  2,error

        if(size >  0)

        {

            //当向服务器发送 “quit” 命令时,服务器首先断开连接

            write(s,buffer,strlen(buffer)+1);   //向服务器端写

            //等待读取到数据

            for(size = 0 ; size == 0 ; size = read(s,buffer,Buflen) );

            write(1,buffer,strlen(buffer)+1);   //向标准输出写

        }

    }

}

void sig_pipe(int signo)    //传入套接字描述符

{

    printf("Catch a signal\n");

    if(signo == SIGTSTP)

    {

        printf("接收到 SIGTSTP 信号\n");

        int ret = close(s);

        if(ret == 0)

            printf("成功 : 关闭套接字\n");

        else if(ret ==-1 )

            printf("失败 : 未关闭套接字\n");

        exit(1);

    }

}

 

posted @ 2021-12-09 21:45  20191229XYZ  阅读(133)  评论(0)    收藏  举报