socket使用方法_socket调试工具怎么用

socket使用方法_socket调试工具怎么用socketpair函数概要如下:#include#includeintsocketpair(intdomain,inttype,intprotocol,intsv[2]);sys/types.h文件需要用来定义一些C宏常量。sys/socket.h文件必须包含进来定义socketpair函数原型。socketpair函数需要四个参数。他们是:套接口的域

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

socketpair函数概要如下:
#include <sys/types.h>
#include <sys/socket.h>
int socketpair(int domain, int type, int protocol, int sv[2]);
sys/types.h文件需要用来定义一些C宏常量。sys/socket.h文件必须包含进来定义socketpair函数原型。
socketpair函数需要四个参数。他们是:
套接口的域
套接口类型
使用的协议
指向存储文件描述符的指针

类型参数声明了我们希望创建哪种类型的套接口。socketpair函数的选择如下:
SOCK_STREAM
SOCK_DGRAM
对于socketpair函数,protocol参数必须提供为0。
参数sv[2]是接收代表两个套接口的整数数组。每一个文件描述符代表一个套接口,并且与另一个并没有区别。
如果函数成功,将会返回0值。否则将会返回-1表明创建失败,并且errno来表明特定的错误号。

关于流程。socketpair()函数创建出两个进程,fork()之后这两个进程都会执行主程序中的代码,这个一定要注意!尤其是bind的时候,如果bind两次的话,那就会出错了。一般会在子进程里调用一个带死循环的函数,这样就好了。(这个情况的例子会在综合运用中讲解)

一下给出个简单的例子。

// 建立socket对
       #include <sys/types.h>
       #include <sys/socket.h>
    
       #include <stdlib.h>
       #include <stdio.h>
    
       int main ()
       {

         int fd[2];
   
        int r = socketpair( AF_UNIX, SOCK_STREAM, 0, fd );
        if ( r < 0 ) {

          perror( “socketpair()” );
          exit( 1 );
        }
   
        if ( fork() ) {

          /* Parent process: echo client */
          int val = 0;
          close( fd[1] );
          while ( 1 ) {

            sleep( 1 );
            ++val;
            printf( “Sending data: %d\n”, val );
            write( fd[0], &val, sizeof(val) );
            read( fd[0], &val, sizeof(val) );
            printf( “Data received: %d\n”, val );
          }
        }
        else {

          /* Child process: echo server */
          int val;
          close( fd[0] );
          while ( 1 ) {

            read( fd[1], &val, sizeof(val) );
            ++val;
            write( fd[1], &val, sizeof(val) );
          }
        }
      }

在给出一个用sendmsg来传递数据的例子

/*****************************************
*
* Listing 1.2
*
* Example performing I/O on s socket pair:
*
* ******************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>

int main(int argc,char **argv)
{

    int z;        /* Status return code */
    int s[2];    /* Pair of sockets */
struct msghdr msg;
    struct iovec iov[1];
char send_buf[100] = “TEST”;
struct msghdr msgr;
    struct iovec iovr[1];
    char recv_buf[100];

    /*
     * Create a pair of local sockets:
     */
    z = socketpair(AF_LOCAL,SOCK_STREAM,0,s);

    if(z == -1)
    {

        fprintf(stderr,
                “%s:socketpair(AF_LOCAL,SOCK_STREAM,””0)\n”,strerror(errno));
        return 1;    /* Failed */
    }

    /*
     * Sendmsg s[1]:
     */

         bzero(&msg, sizeof(msg));
         msg.msg_name = NULL;        /* attention this is a pointer to void* type */
         msg.msg_namelen = 0;
         iov[0].iov_base = send_buf;
         iov[0].iov_len = sizeof(send_buf);
         msg.msg_iov = iov;
         msg.msg_iovlen = 1;

    printf(“sendmsg begin.\n”);
   z = sendmsg( s[1], &msg, 0 );
   if(z == -1 )
   {

    fprintf(stderr,”Sendmsg failed. errno : %s\n”,strerror(errno));
    return -1;
   }
    printf(“Sendmsg Success!\n”);

    /*
     * Read from socket s[0]:
     */

         bzero(&msg, sizeof(msg));
         msgr.msg_name = NULL;        /* attention this is a pointer to void* type */
         msgr.msg_namelen = 0;
         iovr[0].iov_base = &recv_buf;
         iovr[0].iov_len = sizeof(recv_buf);
         msgr.msg_iov = iovr;
         msgr.msg_iovlen = 1;

         z = recvmsg( s[0], &msgr, 0);
   if(z == -1 )
   {

    fprintf(stderr,”Recvmsg failed. errno : %s\n”,strerror(errno));
    return -1;
   }
    printf(“Recvmsg Success!\n”);
printf(“recvmsg : %s\n”, recv_buf);

    /*
     * Close the sockets:
     */
    close(s[0]);
    close(s[1]);

    puts(“Done”);
    return 0;
}

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/sunnyboychina/archive/2007/11/14/1884076.aspx

ttp://bigwhite.blogbus.com/logs/2585693.html

我们知道父进程在子进程被fork出来之前打开的文件描述符是能被子进程继承下来的,但是一旦子进程已经创建后,父进程打开的文件描述符要怎样才能传递给子进程呢?Unix提供相应的技术来满足这一需求,这就是同一台主机上进程间的文件描述符传递,很美妙而且强大的技术。

想象一下我们试图实现一个服务器,接收多个客户端的连接,我们欲采用多个子进程并发的形式来处理多客户端的同时连接,这时候我们可能有两种想法:
1、客户端每建立一条连接,我们fork出一个子进程负责处理该连接;
2、预先创建一个进程池,客户端每建立一条链接,服务器就从该池中选出一个空闲(Idle)子进程来处理该连接。
后者显然更高效,因为减少了子进程创建的性能损耗,反应的及时性大大增强。这里恰恰就出现了我们前面提到的问题,所有子进程都是在服务器Listen到一条连接以前就已经fork出来了,也就是说新的连接描述符子进程是不知道的,需要父进程传递给它,它接收到相应的连接描述符后,才能与相应的客户端进行通信处理。这里我们就可以使用’传递文件描述符’的方式来实现。

在’UNIX网络编程第1卷’的14.7小节中对这种技术有详细的阐述,实际上这种技术就是利用sendmsg和recvmsg在一定的UNIX域套接口(或者是某种管道)上发送和接收一种特殊的消息,这种消息可以承载’文件描述符’罢了,当然操作系统内核对这种消息作了特殊的处理。在具体一点儿’文件描述符’是作为辅助数据(Ancillary Data)通过msghdr结构中的成员msg_control(老版本中称为msg_accrights)发送和接收的。值得一提的是发送进程在将’文件描述符’发送出去后,即使立即关闭该文件描述符,该文件描述符对应的文件设备也没有被真正的关闭,其引用计数仍然大于一,直到接收进程成功接收后,再关闭该文件描述符,如果这时文件设备的引用计数为0,那么才真正关闭该文件设备。

OK,下面是一个简单的文件描述符传递的例子,该例子实现这样一个功能:即子进程负责在父进程传递给它的文件描述符对应的文件尾加上特定的’LOGO’字符串。例子环境为Solaris 9 + GCC 3.2

/* test_fdpass.c */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

#include <sys/socket.h> /* for socketpair */

#define MY_LOGO         “– Tony Bai”

static int send_fd(int fd, int fd_to_send)
{

        struct iovec    iov[1];
        struct msghdr   msg;
        char            buf[1];

        if (fd_to_send >= 0) {

                msg.msg_accrights       = (caddr_t)&fd_to_send;
                msg.msg_accrightslen    = sizeof(int);
        } else {

                msg.msg_accrights       = (caddr_t)NULL;
                msg.msg_accrightslen    = 0;
        }

        msg.msg_name    = NULL;
        msg.msg_namelen = 0;

        iov[0].iov_base = buf;
        iov[0].iov_len = 1;
        msg.msg_iov     = iov;
        msg.msg_iovlen = 1;

        if(sendmsg(fd, &msg, 0) < 0) {

                printf(“sendmsg error, errno is %d\n”, errno);
                return errno;
        }

        return 0;
}

static int recv_fd(int fd, int *fd_to_recv)
{

        struct iovec    iov[1];
        struct msghdr   msg;
        char            buf[1];

        msg.msg_accrights       = (caddr_t)fd_to_recv;
        msg.msg_accrightslen    = sizeof(int);

        msg.msg_name    = NULL;
        msg.msg_namelen = 0;

        iov[0].iov_base = buf;
        iov[0].iov_len = 1;
        msg.msg_iov     = iov;
        msg.msg_iovlen = 1;

        if (recvmsg(fd, &msg, 0) < 0) {

                return errno;
        }

        if(msg.msg_accrightslen != sizeof(int)) {

                *fd_to_recv = -1;
        }

        return 0;
}

int x_sock_set_block(int sock, int on)
{

        int             val;
        int             rv;

        val = fcntl(sock, F_GETFL, 0);
        if (on) {

                rv = fcntl(sock, F_SETFL, ~O_NONBLOCK&val);
        } else {

                rv = fcntl(sock, F_SETFL, O_NONBLOCK|val);
        }

        if (rv) {

                return errno;
        }

        return 0;
}

int main() {

        pid_t   pid;
        int     sockpair[2];
        int     rv;
        char    fname[256];
        int     fd;

        rv = socketpair(AF_UNIX, SOCK_STREAM, 0, sockpair);
        if (rv < 0) {

                printf(“Call socketpair error, errno is %d\n”, errno);
                return errno;
        }

        pid = fork();
        if (pid == 0) {

                /* in child */
                close(sockpair[1]);

                for ( ; ; ) {

                        rv = x_sock_set_block(sockpair[0], 1);
                        if (rv != 0) {

                                printf(“[CHILD]: x_sock_set_block error, errno is %d\n”, rv);
                                break;
                        }

                        rv = recv_fd(sockpair[0], &fd);
                        if (rv < 0) {

                                printf(“[CHILD]: recv_fd error, errno is %d\n”, rv);
                                break;
                        }

                        if (fd < 0) {

                                printf(“[CHILD]: child process exit normally!\n”);
                                break;
                        }

                      /* 处理fd描述符对应的文件 */
                        rv = write(fd, MY_LOGO, strlen(MY_LOGO));
                        if (rv < 0) {

                                printf(“[CHILD]: write error, errno is %d\n”, rv);
                        } else {

                                printf(“[CHILD]: append logo successfully\n”);
                        }
                        close(fd);
                }

                exit(0);
        }

        /* in parent */
        for ( ; ; ) {

                memset(fname, 0, sizeof(fname));
                printf(“[PARENT]: please enter filename:\n”);
                scanf(“%s”, fname);

                if (strcmp(fname, “exit”) == 0) {

                        rv = send_fd(sockpair[1], -1);
                        if (rv < 0) {

                                printf(“[PARENT]: send_fd error, errno is %d\n”, rv);
                        }
                        break;
                }

                fd = open(fname, O_RDWR | O_APPEND);
                if (fd < 0) {

                        if (errno == ENOENT) {

                                printf(“[PARENT]: can’t find file ‘%s’\n”, fname);
                                continue;
                        }
                        printf(“[PARENT]: open file error, errno is %d\n”, errno);
                }

                 rv = send_fd(sockpair[1], fd);
                if (rv != 0) {

                        printf(“[PARENT]: send_fd error, errno is %d\n”, rv);
                }

                close(fd);
        }

        wait(NULL);
        return 0;
}

编译:gcc -o test_fdpass -lsocket -lnsl test_fdpass.c
执行:test_fdpass(事先在同一目录下创建一个文件kk.log)

[PARENT]: please enter filename:
kk.log
[CHILD]: append logo successfully
[PARENT]: please enter filename:
cc.log
[PARENT]: can’t find file ‘cc.log’
exit
[CHILD]: child process exit normally!

你可以发现kk.log内容的末尾已经加上了我的独特LOGO ‘– Tony Bai’。^_^
关于文件描述符传递的更多细节, W. Richard Stevens的’UNIX网络编程第1卷’和’UNIX环境高级编程’两本书中都有详细说明,参读即可。

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/182142.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • JavaFX Script语言教程「建议收藏」

    JavaFX Script语言教程「建议收藏」JavaFXScript™(下文中称为JavaFX)语言是一种声明式的静态类型编程语言。它具有第一级函数(first-classfunctions)、声明式的语法、列表推导(list-comprehensions)及基于依赖关系的增量式求值(incrementaldependency-basedevaluation)等特征。JavaFX脚本式语言特别适用于Java2Dswi…

  • Oracle 恢复数据到某个时间节点

    Oracle 恢复数据到某个时间节点–注意:恢复的时间点与当前时间节点表结构需要一致,truncate的数据无法恢复–1.创建临时表保存该时间节点表的数据createtabletemp_table–临时表asselect*fromT_PM_ParamItem–原表asoftimestampto_timestamp(‘2018-01-1211:11:11’,’yyyy-mm-ddhh24…

  • c语言自定义BOOL函数

    c语言自定义BOOL函数C语言中没有BOOL类型变量,它是C++独有的,由于使用BOOL类型可以使代码更具有可读性,很多编程者都在C中自己定义了类似的应用,一般方法有两种:第一种:采用宏定义方式typedefintBOOL;#definetrue1#definefalse0或写为:#ifndefbool#defineboolint#endif#ifndeftrue…

  • HttpClient默认重试策略不处理SocketTimeoutException

    HttpClient默认重试策略不处理SocketTimeoutException

  • 电流转电压模块4-20mA转0-3.3/5V/10V/15V转换变送器电路原理解析

    电流转电压模块4-20mA转0-3.3/5V/10V/15V转换变送器电路原理解析工业传感器常使用电流大小来传输数据,那么作为传感器数据的接收方,比如单片机,有内部AD的单片机可以检测电压的大小,那么首先必须将电流信号转换为电压信号,然后进行电压幅值变换使其适合MCU处理的电压范围。下面我们从设计的电流转电压的模块电路原理图来逐步解析。首先我们看电流检测放大部分,就是U1B部分,电流从R1的上端流入,下端流出。不难看出这是一个差分放大电路,也就是一个减…

  • 新手上路:ADAMS 基础知识讲解(图文并茂)【转载仿真论坛】(三)

    新手上路:ADAMS 基础知识讲解(图文并茂)【转载仿真论坛】(三)引用Baker的新手上路:ADAMS基础知识讲解(图文并茂)【转载仿真论坛】(三)四、常见问题篇1、ADAMS中的单位的问题开始的时候需要为模型设置单位。在所有的预置单位系统中,时间单位是秒,角度是度。可设置:MMKS–设置长度为千米,质量为千克,力为牛顿。MKS—设置长度为米,质量为千克,力为牛顿。CGS—设置长度为厘米,质量为克,力为达因。IPS—设置长度为英寸,质量为斯勒格(

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号