这几天学习网络编程,踩了好多坑,网上这部分资料不多,例子也是抄来抄去。
sendmsg和recvmsg这两个接口是高级套接口,这两个接口支持一般数据的发送和接收,还支持多缓冲区的报文发送和接收(readv和sendv支持多缓冲区发送和接收),还可以在报文中带辅助数据。
还是先上代码
#include
#include
#include
#include
#include
#include
#include
#define DEFAULT_PORT 8080
#define MAXLINE 4096
#define MAX_NAME_LEN 4095
#define MAX_MMSG_NUM 10
int receive_message(int socket_fd, int* socket_num, int* sockets) {
struct iovec iov[1];
int32_t utm[MAX_MMSG_NUM];
char buf[CMSG_SPACE(sizeof(int) * MAX_MMSG_NUM)];
struct msghdr msg;
{
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_flags = 0;
msg.msg_iov = iov;
//msg.msg_iov = 0;
msg.msg_iovlen = sizeof(iov) /sizeof(iov[0]);
//msg.msg_iovlen = 0;
msg.msg_control = buf;
//msg.msg_control = NULL;
msg.msg_controllen = sizeof(buf);
//msg.msg_controllen = 0;
msg.msg_iov[0].iov_base = utm;
msg.msg_iov[0].iov_len = sizeof(utm);
}
errno = 0;
const int n = recvmsg(socket_fd, &msg, MSG_WAITALL);
std::cout << "receive finish n=" << n << "sizeof(utm)=" << sizeof(utm) << std::endl;
struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
{
if (n <= 0) {
std::cout << "receive message faild, return " << strerror(errno) << std::endl;
return errno;
}
if(0 != (msg.msg_flags & (MSG_TRUNC | MSG_CONFIRM))) {
std::cout << "receive message truncated, flags=" << msg.msg_flags << std::endl;
return errno;
}
}
*socket_num = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int32_t);
int32_t* fd_arr = reinterpret_cast(CMSG_DATA(cmsg));
for (int32_t i = 0; i < *socket_num; i++) {
sockets[i] = fd_arr[i];
std::cout << "the data recv is " << utm[i] <<" " << sockets[i] << std::endl;
}
return 0;
}
int main(int argc, char** argv) {
int socket_fd;
int connect_fd;
int num = 0;
//struct sockaddr_in servaddr;//net conn
struct sockaddr_un servaddr;//local conn
char buff[4096];
#if 0
//init the socket
std::cout << "create socket error" << std::endl;
if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
exit(1);
}
// init the in struct
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//set the server ip
servaddr.sin_port = htons(DEFAULT_PORT);//set the listion port
#else
unlink("server_socket");
if ((socket_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
std::cout << "create socket error" << std::endl;
exit(1);
}
servaddr.sun_family = AF_UNIX;
snprintf(servaddr.sun_path, MAX_NAME_LEN, "%s", "server_socket");
#endif
//bind the struct to the socket
if ( bind(socket_fd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1 ) {
std::cout << "bind socket error: " << strerror(errno) <<std::endl;
exit(1);
}
//listion the socket 10 is the max conn num
if ( listen(socket_fd, 10) == -1 ) {
std::cout << "listen error" << std::endl;
}
std::cout << "start to listen 8080 port" << std::endl;
connect_fd = accept(socket_fd, (struct sockaddr*)NULL, NULL);
if ( connect_fd == -1 ) {
std::cout << "accept socket error" << strerror(errno) << std::endl;
}
#if 0
while(true) {
num = recv(connect_fd, buff, MAXLINE, 0);
if (num < 0) {
std::cout << "receive error" << strerror(errno) << std::endl;
}
buff[num] = '\0';
std::cout << "receive from client " << buff << std::endl;
if ( send(connect_fd, "we have received your message", 29, 0) == -1 ) {
std::cout << "send error" << strerror(errno) << std::endl;
}
sleep(3);
}
#else
int socket_num = 0;
int socket_array [MAX_MMSG_NUM];
receive_message(connect_fd, &socket_num, socket_array);
#endif
}
/* vim: set ts=4 sw=4 sts=4 tw=100 */
#include
#include
#include
#include
#include
#include
#include
#define DEFAULT_PORT 8080
#define MAXLINE 4096
#define MAX_NAME_LEN 4095
#define MAX_MMSG_NUM 10
//send fd to server with sendmsg
int write_message(int socket_fd, int socket_num, int32_t* socket_array, int32_t* data) {
struct iovec iov[1];
char buf[CMSG_SPACE(sizeof(int) * MAX_MMSG_NUM)];
struct msghdr msg;
{
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_flags = 0;
msg.msg_iov = iov;
//msg.msg_iov = 0;
msg.msg_iovlen = sizeof(iov) / sizeof(iov[0]);
//msg.msg_iovlen = 0;
msg.msg_control = buf;
//msg.msg_control = NULL;
msg.msg_controllen = sizeof(buf);
//msg.msg_controllen = 0;
iov[0].iov_base = const_cast(data);
iov[0].iov_len = sizeof(data[0]) * MAX_MMSG_NUM;
struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int32_t) * socket_num);
int32_t* fdptr = reinterpret_cast(CMSG_DATA(cmsg));
for (uint32_t i = 0; i < socket_num; i++) {
fdptr[i] = static_cast(socket_array[i]);
}
msg.msg_controllen = CMSG_SPACE(sizeof(int32_t) * socket_num);
}
//send info to client
while (true) {
errno = 0;
const ssize_t n = sendmsg(socket_fd, &msg, 0);
if (-1 == n) {
std::cout << "send message error " << strerror(errno) << std::endl;
if (EINTR == errno) {
continue;
}
return errno;
}
std::cout << "sendmsg success n = " << n << std::endl;
break;
}
return 0;
}
int main(int argc, char** argv) {
int socket_fd;
int num = 0;
int rec_len = 0;
//struct sockaddr_in servaddr;// net conn
struct sockaddr_un servaddr;//local conn
char recvline[4096];
char sendline[4096];
char buff[MAXLINE];
// apply socket_fd
#if 0
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (socket_fd == -1) {
std::cout << "create socket error" << std::endl;
exit(1);
}
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(DEFAULT_PORT);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
//transfer ip
#else
socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (socket_fd == -1) {
std::cout << "create socket error" << std::endl;
exit(1);
}
servaddr.sun_family = AF_UNIX;
snprintf(servaddr.sun_path, MAX_NAME_LEN, "%s", "server_socket");
#endif
int ret = 0;
//conn
ret = connect(socket_fd, (struct sockaddr*)&servaddr, sizeof(servaddr));
if (ret < 0) {
std::cout << "connect error " << strerror(errno) << std::endl;
exit(1);
}
std::cout << "send message to server" << std::endl;
#if 0
std::string msg = "hello server!";
strcpy(sendline, msg.c_str());
int time = 3;
while(time > 0) {
ret = send(socket_fd, sendline, strlen(msg.c_str()), 0);
if (ret < 0) {
std::cout << "send msg error" << strerror(errno) << std::endl;
continue;
}
std::cout << "send again" << std::endl;
time--;
}
rec_len = recv (socket_fd, buff, MAXLINE, 0);
if (rec_len < 0) {
std::cout << "recv msg error" << strerror(errno) << std::endl;
}
buff[rec_len] = '\0';
std::cout << "received " << buff << std::endl;
#else
int32_t array[MAX_MMSG_NUM];
for (int i = 0; i < MAX_MMSG_NUM; i++) {
array[i] = socket(AF_UNIX, SOCK_STREAM, 0);
}
int32_t data[MAX_MMSG_NUM];
for (int i = 0; i < MAX_MMSG_NUM; i++) {
data[i] = i;
std::cout << "the data adn fd is " << data[i] << " " <<array[i] << std::endl;
}
write_message(socket_fd, MAX_MMSG_NUM, array, data);
#endif
close(socket_fd);
}
/* vim: set ts=4 sw=4 sts=4 tw=100 */