gpt4 book ai didi

c++ - 在两个客户端套接字之间发送数据

转载 作者:太空宇宙 更新时间:2023-11-04 08:48:03 36 4
gpt4 key购买 nike

我必须在 Mac-OS 上使用 C 套接字制作一个应用程序,将数据从一个套接字发送到另一个套接字,就像这样。

  1. 服务器等待连接
  2. 客户端连接到服务器(从 1)。 -> 套接字 1
  3. 服务器连接到外部服务器并获得套接字。 -> 套接字2

从现在开始,服务器工作已经完成。数据交换应该只在客户端套接字(来自 2)和从 3 获得的套接字之间进行。

当前实现:服务器建立连接,然后从一个套接字读取数据并发送到另一个套接字。

任何想法如何在第 3 步之后通过管道连接两个套接字 socket1 和 socket2。

最佳答案

您的问题可以通过两种方式解决:

1) 您需要编写与客户端和外部服务器之间的连接形成相关的部分。但这会给客户端带来额外的负担,因为它需要与两个服务器建立两个连接(我强烈认为在这种情况下中间服务器是无用的)。

2) 第二种解决方法是在服务器之间传递套接字:客户端连接到服务器,这个中间服务器将这个套接字发送到外部服务器。现在外部服务器开始与客户端通信。仅当两个服务器进程都在同一台机器上运行时才能这样做。文件描述符通常使用 Unix Domain Sockets 传递。

这是我的代码。您可以使用这两个函数来发送或接收文件描述符。它适用于我的 Linux 机器。我不知道 Mac-OS。

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/uio.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
/* this function passes 'fd_to_send'
file descriptor via
a unix domain socket 'sfd'...
*/
void pass_fd(int sfd, int fd_to_send)
{
struct msghdr msg;

/*allocate memory to 'msg_control' field in msghdr struct */
char buf[CMSG_SPACE(sizeof(int))];
/*the memory to be allocated should include data + header..
this is calculated by the above macro...(it merely adds some
no. of bytes and returs that number..*/

struct cmsghdr *cmsg;

struct iovec ve;
/*must send/receive atleast one byte...
main purpose is to have some error
checking.. but this is completely
irrelevant in the current context..*/

char *st ="I";
/*jst let us allocate 1 byte for formality
and leave it that way...*/
ve.iov_base = st;
ve.iov_len =1;

/*attach this memory to our main msghdr struct...*/
msg.msg_iov = &ve;
msg.msg_iovlen = 1;

/*these are optional fields ..
leave these fields with zeros..
to prevent unnecessary SIGSEGVs..*/
msg.msg_name = NULL;
msg.msg_namelen = 0;


/*here starts the main part..*/
/*attach the 'buf' to msg_control..
and fill in the size field correspondingly..
*/

msg.msg_control = buf;
msg.msg_controllen = sizeof(buf);

/*actually msg_control field must
point to a struct of type 'cmsghdr'
we just allocated the memory, yet we need to
set all the corresponding fields..
It is done as follows:
*/
cmsg = CMSG_FIRSTHDR(&msg);
/* this macro returns the address in the buffer..
from where the first header starts..
*/

/*set all the fields appropriately..*/
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(fd_to_send));
/*in the above field we need to store
the size of header + data(in this case 4 bytes(int) for our fd..
this is returned by the 'CMSG_LEN' macro..*/

*(int*)CMSG_DATA(cmsg) = fd_to_send;
/*after the above three fields we keep the actual data..
the macro 'CMSG_DATA' returns pointer to this location
and we set it to the file descriptor to be sent..
*/

msg.msg_controllen = cmsg->cmsg_len;
/*now that we have filled the 'cmsg' struct
we store the size of this struct..*/
/*this one isn't required when you
pass a single fd..
but useful when u pass multiple fds.*/

msg.msg_flags = 0;
/*leave the flags field zeroed..*/

if(sendmsg( sfd, &msg, 0)==-1){ perror("snd:\n"); exit(1); }
/*send this over the UNIX deomain socoket..*/
printf("sent fd:%d\n", fd_to_send);
close(fd_to_send);
/*close the fd which was sent..*/
}
/*returns the received fd over the unix domain socket 'sfd'..*/
int recv_fd(int sfd)
{
struct msghdr msg;
/*do all the unwanted things first...
same as the send_fd function..*/
struct iovec io;
char ptr[1];
io.iov_base = ptr;
io.iov_len = 1;
msg.msg_name = 0;
msg.msg_namelen = 0;
msg.msg_iov = &io;
msg.msg_iovlen = 1;
/*-----------------------*/


char buf[CMSG_SPACE(sizeof(int))];
msg.msg_control = buf;
msg.msg_controllen = sizeof(buf);
/*reasoning is same..as above*/

/*now here comes the main part..*/

if(recvmsg( sfd, &msg, 0)==-1)
{
/*some shit has happened*/
perror("recv\n");
exit(1);
}

struct cmsghdr *cm;

cm = CMSG_FIRSTHDR(&msg);
/*get the first message header..*/

if(cm->cmsg_type != SCM_RIGHTS)
{
/*again some shit has happened..*/
perror("unknown type..\n");
exit(1);
}

/*if control has reached here.. this means
we have got the correct message..and when you
extract the fd out of this message
this need not be same as the one which was sent..
allocating a new fd is all done by the kernel
and our job is jst to use it..*/
printf("received fd:%d\n", *(int*)CMSG_DATA(cm));
return *(int*)CMSG_DATA(cm);
}

关于c++ - 在两个客户端套接字之间发送数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20869973/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com