Linux下TCP Socket编程C语言小实例


TCPServer端

  1. #include <stdio.h>   
  2. #include <stdlib.h>   
  3. #include <strings.h>   
  4. #include <sys/types.h>   
  5. #include <sys/socket.h>   
  6. #include <memory.h>   
  7. #include <unistd.h>   
  8. //#include <linux/in.h>   
  9. #include <netinet/in.h>   
  10. //#include <linux/inet_diag.h>   
  11. #include <arpa/inet.h>   
  12.   
  13. #include <signal.h>   
  14.   
  15. /** 
  16.   关于 sockaddr  sockaddr_in  socketaddr_un说明 
  17.   http://maomaozaoyue.blog.sohu.com/197538359.html 
  18.   */  
  19.   
  20. #define PORT    11910   //定义通信端口   
  21. #define BACKLOG 5       //定义侦听队列长度   
  22. #define buflen  1024   
  23.   
  24. void process_conn_server(int s);  
  25. void sig_pipe(int signo);  
  26.   
  27. int ss,sc;  //ss为服务器socket描述符,sc为某一客户端通信socket描述符   
  28.   
  29. int main(int argc,char *argv[])  
  30. {  
  31.   
  32.     struct sockaddr_in server_addr; //存储服务器端socket地址结构   
  33.     struct sockaddr_in client_addr; //存储客户端 socket地址结构   
  34.   
  35.     int err;    //返回值   
  36.     pid_t pid;  //分叉进行的ID   
  37.   
  38.     /*****************socket()***************/  
  39.     ss = socket(AF_INET,SOCK_STREAM,0); //建立一个序列化的,可靠的,双向连接的的字节流   
  40.     if(ss<0)  
  41.     {  
  42.         printf("server : server socket create error\n");  
  43.         return -1;  
  44.     }  
  45.     //注册信号   
  46.     sighandler_t ret;  
  47.     ret = signal(SIGTSTP,sig_pipe);  
  48.     if(SIG_ERR == ret)  
  49.     {  
  50.         printf("信号挂接失败\n");  
  51.         return -1;  
  52.     }  
  53.     else  
  54.         printf("信号挂接成功\n");  
  55.   
  56.   
  57.     /******************bind()****************/  
  58.     //初始化地址结构   
  59.     memset(&server_addr,0,sizeof(server_addr));  
  60.     server_addr.sin_family = AF_INET;           //协议族   
  61.     server_addr.sin_addr.s_addr = htonl(INADDR_ANY);   //本地地址   
  62.     server_addr.sin_port = htons(PORT);  
  63.   
  64.     err = bind(ss,(struct sockaddr *)&server_addr,sizeof(sockaddr));  
  65.     if(err<0)  
  66.     {  
  67.         printf("server : bind error\n");  
  68.         return -1;  
  69.     }  
  70.   
  71.     /*****************listen()***************/  
  72.     err = listen(ss,BACKLOG);   //设置监听的队列大小   
  73.     if(err < 0)  
  74.     {  
  75.         printf("server : listen error\n");  
  76.         return -1;  
  77.     }  
  78.   
  79.     /****************accept()***************/  
  80.     /** 
  81.     为类方便处理,我们使用两个进程分别管理两个处理: 
  82.     1,服务器监听新的连接请求;2,以建立连接的C/S实现通信 
  83.     这两个任务分别放在两个进程中处理,为了防止失误操作 
  84.     在一个进程中关闭 侦听套接字描述符 另一进程中关闭 
  85.     客户端连接套接字描述符。注只有当所有套接字全都关闭时 
  86.     当前连接才能关闭,fork调用的时候父进程与子进程有相同的 
  87.     套接字,总共两套,两套都关闭掉才能关闭这个套接字 
  88.     */  
  89.   
  90.     for(;;)  
  91.     {  
  92.         socklen_t addrlen = sizeof(client_addr);  
  93.         //accept返回客户端套接字描述符   
  94.         sc = accept(ss,(struct sockaddr *)&client_addr,&addrlen);  //注,此处为了获取返回值使用 指针做参数   
  95.         if(sc < 0)  //出错   
  96.         {  
  97.             continue;   //结束此次循环   
  98.         }  
  99.         else  
  100.         {  
  101.             printf("server : connected\n");  
  102.         }  
  103.   
  104.         //创建一个子线程,用于与客户端通信   
  105.         pid = fork();  
  106.         //fork 调用说明:子进程返回 0 ;父进程返回子进程 ID   
  107.         if(pid == 0)        //子进程,与客户端通信   
  108.         {  
  109.             close(ss);  
  110.             process_conn_server(sc);  
  111.         }  
  112.         else  
  113.         {  
  114.             close(sc);  
  115.         }  
  116.     }  
  117. }  
  118.   
  119. /** 
  120.   服务器对客户端连接处理过程;先读取从客户端发送来的数据, 
  121.   然后将接收到的数据的字节的个数发送到客户端 
  122.   */  
  123.   
  124. //通过套接字 s 与客户端进行通信   
  125. void process_conn_server(int s)  
  126. {  
  127.     ssize_t size = 0;  
  128.     char buffer[buflen];  //定义数据缓冲区   
  129.     for(;;)  
  130.     {  
  131.         //等待读   
  132.         for(size = 0;size == 0 ;size = read(s,buffer,buflen));  
  133.         //输出从客户端接收到的数据   
  134.         printf("%s",buffer);  
  135.   
  136.         //结束处理   
  137.         if(strcmp(buffer,"quit") == 0)  
  138.         {  
  139.             close(s);   //成功返回0,失败返回-1   
  140.             return ;  
  141.         }  
  142.         sprintf(buffer,"%d bytes altogether\n",size);  
  143.         write(s,buffer,strlen(buffer)+1);  
  144.     }  
  145. }  
  146. void sig_pipe(int signo)  
  147. {  
  148.     printf("catch a signal\n");  
  149.     if(signo == SIGTSTP)  
  150.     {  
  151.         printf("接收到 SIGTSTP 信号\n");  
  152.         int ret1 = close(ss);  
  153.         int ret2 = close(sc);  
  154.         int ret = ret1>ret2?ret1:ret2;  
  155.         if(ret == 0)  
  156.             printf("成功 : 关闭套接字\n");  
  157.         else if(ret ==-1 )  
  158.             printf("失败 : 未关闭套接字\n");  
  159.   
  160.         exit(1);  
  161.     }  
  162. }  
#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

    /*****************socket()***************/
    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");


    /******************bind()****************/
    //初始化地址结构
    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;
    }

    /*****************listen()***************/
    err = listen(ss,BACKLOG);   //设置监听的队列大小
    if(err < 0)
    {
        printf("server : listen error\n");
        return -1;
    }

    /****************accept()***************/
    /**
    为类方便处理,我们使用两个进程分别管理两个处理:
    1,服务器监听新的连接请求;2,以建立连接的C/S实现通信
    这两个任务分别放在两个进程中处理,为了防止失误操作
    在一个进程中关闭 侦听套接字描述符 另一进程中关闭
    客户端连接套接字描述符。注只有当所有套接字全都关闭时
    当前连接才能关闭,fork调用的时候父进程与子进程有相同的
    套接字,总共两套,两套都关闭掉才能关闭这个套接字
    */

    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);
    }
}



TCPClient端


  1. #include <stdio.h>   
  2. #include <strings.h>   
  3. #include <unistd.h>   
  4. #include <sys/types.h>   
  5. #include <sys/socket.h>   
  6. //#include <linux/in.h>   
  7. #include <stdlib.h>   
  8. #include <memory.h>   
  9. #include <arpa/inet.h>   
  10. #include <netinet/in.h>   
  11.   
  12. #include <signal.h> //添加信号处理  防止向已断开的连接通信   
  13.   
  14. /** 
  15.   信号处理顺序说明:在Linux操作系统中某些状况发生时,系统会向相关进程发送信号, 
  16.   信号处理方式是:1,系统首先调用用户在进程中注册的函数,2,然后调用系统的默认 
  17.   响应方式,此处我们可以注册自己的信号处理函数,在连接断开时执行 
  18.   */  
  19.   
  20.   
  21. #define PORT    11910   
  22. #define Buflen  1024   
  23.   
  24. void process_conn_client(int s);  
  25. void sig_pipe(int signo);    //用户注册的信号函数,接收的是信号值   
  26.   
  27. int s;  //全局变量 , 存储套接字描述符   
  28.   
  29. int main(int argc,char *argv[])  
  30. {  
  31.   
  32.     sockaddr_in server_addr;  
  33.     int err;  
  34.     sighandler_t ret;  
  35.     char server_ip[50] = "";  
  36.     /********************socket()*********************/  
  37.     s= socket(AF_INET,SOCK_STREAM,0);  
  38.     if(s<0)  
  39.     {  
  40.         printf("client : create socket error\n");  
  41.         return 1;  
  42.     }  
  43.   
  44.     //信号处理函数  SIGINT 是当用户按一个 Ctrl-C 建时发送的信号   
  45.     ret = signal(SIGTSTP,sig_pipe);  
  46.     if(SIG_ERR == ret)  
  47.     {  
  48.         printf("信号挂接失败\n");  
  49.         return -1;  
  50.     }  
  51.     else  
  52.         printf("信号挂接成功\n") ;  
  53.   
  54.   
  55.     /*******************connect()*********************/  
  56.     //设置服务器地址结构,准备连接到服务器   
  57.     memset(&server_addr,0,sizeof(server_addr));  
  58.     server_addr.sin_family = AF_INET;  
  59.     server_addr.sin_port = htons(PORT);  
  60.     server_addr.sin_addr.s_addr = htonl(INADDR_ANY);  
  61.   
  62.     /*将用户数入对额字符串类型的IP格式转化为整型数据*/  
  63.     //inet_pton(AF_INET,argv[1],&server_addr.sin_addr.s_addr);   
  64.     printf("please input server ip address : \n");  
  65.     read(0,server_ip,50);  
  66.     //err = inet_pton(AF_INET,server_ip,&server_addr.sin_addr.s_addr);   
  67.     server_addr.sin_addr.s_addr = inet_addr(server_ip);  
  68.   
  69.     err = connect(s,(struct sockaddr *)&server_addr,sizeof(sockaddr));  
  70.     if(err == 0)  
  71.     {  
  72.         printf("client : connect to server\n");  
  73.     }  
  74.     else  
  75.     {  
  76.         printf("client : connect error\n");  
  77.         return -1;  
  78.     }  
  79.     //与服务器端进行通信   
  80.     process_conn_client(s);  
  81.     close(s);  
  82.   
  83. }  
  84. void process_conn_client(int s)  
  85. {  
  86.   
  87.     ssize_t size = 0;  
  88.     char buffer[Buflen];  
  89.   
  90.     for(;;)  
  91.     {  
  92.         memset(buffer,'\0',Buflen);  
  93.         /*从标准输入中读取数据放到缓冲区buffer中*/  
  94.         size = read(0,buffer,Buflen);   // 0,被默认的分配到标准输入  1,标准输出  2,error   
  95.         if(size >  0)  
  96.         {  
  97.             //当向服务器发送 “quit” 命令时,服务器首先断开连接   
  98.             write(s,buffer,strlen(buffer)+1);   //向服务器端写   
  99.   
  100.             //等待读取到数据   
  101.             for(size = 0 ; size == 0 ; size = read(s,buffer,Buflen) );  
  102.   
  103.             write(1,buffer,strlen(buffer)+1);   //向标准输出写   
  104.         }  
  105.     }  
  106. }  
  107.   
  108. void sig_pipe(int signo)    //传入套接字描述符   
  109. {  
  110.     printf("Catch a signal\n");  
  111.     if(signo == SIGTSTP)  
  112.     {  
  113.   
  114.         printf("接收到 SIGTSTP 信号\n");  
  115.         int ret = close(s);  
  116.         if(ret == 0)  
  117.             printf("成功 : 关闭套接字\n");  
  118.         else if(ret ==-1 )  
  119.             printf("失败 : 未关闭套接字\n");  
  120.         exit(1);  
  121.     }  
  122. }  
#include <stdio.h>
#include <strings.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
//#include <linux/in.h>
#include <stdlib.h>
#include <memory.h>
#include <arpa/inet.h>
#include <netinet/in.h>

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

/**
  信号处理顺序说明:在Linux操作系统中某些状况发生时,系统会向相关进程发送信号,
  信号处理方式是:1,系统首先调用用户在进程中注册的函数,2,然后调用系统的默认
  响应方式,此处我们可以注册自己的信号处理函数,在连接断开时执行
  */


#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] = "";
    /********************socket()*********************/
    s= socket(AF_INET,SOCK_STREAM,0);
    if(s<0)
    {
        printf("client : create socket error\n");
        return 1;
    }

    //信号处理函数  SIGINT 是当用户按一个 Ctrl-C 建时发送的信号
    ret = signal(SIGTSTP,sig_pipe);
    if(SIG_ERR == ret)
    {
        printf("信号挂接失败\n");
        return -1;
    }
    else
        printf("信号挂接成功\n") ;


    /*******************connect()*********************/
    //设置服务器地址结构,准备连接到服务器
    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);

    /*将用户数入对额字符串类型的IP格式转化为整型数据*/
    //inet_pton(AF_INET,argv[1],&server_addr.sin_addr.s_addr);
    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);
    }
}



运行结果

TCPServer端


TCPClient端


netstat查看网络连接


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值