[转]network programming in the kernel-凯发app官方网站

凯发app官方网站-凯发k8官网下载客户端中心 | | 凯发app官方网站-凯发k8官网下载客户端中心
  • 博客访问: 3976852
  • 博文数量: 536
  • 博客积分: 10470
  • 博客等级: 上将
  • 技术积分: 4825
  • 用 户 组: 普通用户
  • 注册时间: 2006-05-26 14:08
文章分类

全部博文(536)

文章存档

2024年(3)

2021年(1)

2019年(1)

2017年(1)

2016年(2)

2013年(2)

2012年(10)

2011年(43)

2010年(10)

2009年(17)

2008年(121)

2007年(252)

2006年(73)

分类:

2007-07-03 18:21:05

i have implemented sockets in kernel 2.6 and made simple functions like userspace. (i made for tcp but i think udp can also be done in a similar manner)

here is the complete code. i think the function names are self explanatory. first to use sockets, you have to create a struct socket objects.
for a server, use set_up_server_socket, followed by server_accept connection and for the client use set_up_client_socket. to send and recieve messages use the sendbuffer and recvbuffer functions.

/*
  sendbuffer sends "length" bytes from "buffer" through the socket "sock".
 */

size_t sendbuffer(struct socket *sock, const char *buffer, size_t length)
{
  struct msghdr msg;
  mm_segment_t oldfs; // mm_segment_t is just a long

  struct iovec iov; // structure containing a base addr. and length

  int len2;

  //printk("entering sendbuffer\n");


  msg.msg_name = 0;
  msg.msg_namelen = 0;
  msg.msg_iov = &iov;
  msg.msg_iovlen = 1; //point to be noted

  msg.msg_control = null;
  msg.msg_controllen = 0;

  msg.msg_flags = msg_nosignal; //0/*msg_dontwait*/;


  iov.iov_base = (char*) buffer; // as we know that iovec is

  iov.iov_len = (__kernel_size_t) length; // nothing but a base addr and length


  // #define get_fs() (current_thread_info()->addr_limit)

  // similar for set_fs;


  /*
   therefore this line sets the "fs" to kernel_ds and saves its old value
   */

  oldfs = get_fs();
  set_fs(kernel_ds);

  /* actual sending of the message */
  len2 = sock_sendmsg(sock, &msg, (size_t)(length));

  /* retrieve the old value of fs (whatever it is) */
  set_fs(oldfs);

  return len2;
}


/*
  recieves data from the socket "sock" and puts it in the 'buffer'.
  returns the length of data recieved

  the calling function must do a:
  buffer = (char*) get_free_page(gfp_kernel);
  or a kmalloc to allocate kernel's memory
  (or it can use the kernel's stack space [very small] )
*/

size_t recvbuffer(struct socket *sock, const char *buffer, size_t length)
{
  struct msghdr msg;
  struct iovec iov;
  int len;
  mm_segment_t oldfs;

  /* set the msghdr structure*/
  msg.msg_name = 0;
  msg.msg_namelen = 0;
  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;
  msg.msg_control = null;
  msg.msg_controllen = 0;
  msg.msg_flags = 0;

  /* set the iovec structure*/
  iov.iov_base = (void *) &buffer[0];
  iov.iov_len = (size_t)length;

  /* recieve the message */
  oldfs = get_fs();
  set_fs(kernel_ds);

  len = sock_recvmsg(sock,&msg,length,0/*msg_dontwait*/); // let it wait if there is no message


  set_fs(oldfs);

  // if ((len!=-eagain)&&(len!=0))

  // printk("recvbuffer recieved %i bytes \n",len);


  return len;
}

/*
  sets up a server-side socket

  1. create a new socket
  2. bind the address to the socket
  3. start listening on the socket
*/

struct socket* set_up_server_socket(int port_no)
{
  struct socket *sock;
  struct sockaddr_in sin;

  int error;

  /* first create a socket */
  error = sock_create(pf_inet,sock_stream,ipproto_tcp,&sock) ;
  if (error<0)
    printk("error during creation of socket; terminating\n");

  /* now bind the socket */
  sin.sin_family = af_inet;
  sin.sin_addr.s_addr = inaddr_any;
  sin.sin_port = htons(port_no);

  error = sock->ops->bind(sock,(struct sockaddr*)&sin,sizeof(sin));
  if (error<0)
  {
    printk("error binding socket \n");
    return 0;
  }

  /* now, start listening on the socket */
  error=sock->ops->listen(sock,32);
  if (error!=0)
    printk("error listening on socket \n");

  /* now start accepting */
  // accepting is performed by the function server_accept_connection


  return sock;
}


/*
  accepts a new connection (server calls this function)

  1. create a new socket
  2. call socket->ops->accept
  3. return the newly created socket
 */


struct socket* server_accept_connection(struct socket *sock)
{
  struct socket * newsock;
  int error;

  /* before accept: clone the socket */
  error = sock_create(pf_inet,sock_stream,ipproto_tcp,&newsock);
  if (error<0)
    printk("error during creation of the other socket; terminating\n");

  newsock->type = sock->type;
  newsock->ops=sock->ops;

  /* do the actual accept */
  error = newsock->ops->accept(sock,newsock,0);
  if (error<0)
  {
    /* must add release the socket code here */
    printk("error accepting socket\n") ;
    return 0;
  }

  return newsock;
}

struct socket * set_up_client_socket(unsigned int ip_addr, int port_no)
{
  struct socket *clientsock;
  struct sockaddr_in sin;
  int error, i;

  /* first create a socket */
  error = sock_create(pf_inet,sock_stream,ipproto_tcp,&clien tsock);
  if (error<0)
  {
    printk("error during creation of socket; terminating\n");
    return 0;
  }

  /* now bind and connect the socket */
  sin.sin_family = af_inet;
  sin.sin_addr.s_addr = htonl(ip_addr);
  sin.sin_port = htons(port_no);

  for(i=0; i<10; i)
  {
    error = clientsock->ops->connect(clientsock,(struct sockaddr*)&sin,sizeof(sin),0);
    if (error<0)
     {
      printk("error connecting client socket to server: %i, retrying .. %d \n",error, i);
      if(i == 10-1)
        {
         printk("giving up!\n");
         return 0;
        }
     }
    else
      break; //connected

  }

  return clientsock;
}


部分地方写的还不是很规范, 但总的来说还是很不错, 可以学习学习!

ref:
阅读(2906) | 评论(0) | 转发(0) |
0

上一篇:小金牛

下一篇:寻最佳数据存放格式!

给主人留下些什么吧!~~
")); function link(t){ var href= $(t).attr('href'); href ="?url=" encodeuricomponent(location.href); $(t).attr('href',href); //setcookie("returnouturl", location.href, 60, "/"); }
网站地图