⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 socket.c

📁 很好的网络编程协议源码
💻 C
字号:
/*
+FHDR------------------------------------------------------------------
Copyright (c),
Tony Yang –51,AVR,ARM firmware developer  
Contact:qq 292942278  e-mail:tony_yang123@sina.com.cn

Abstract:
$Id: socket.c,v 1.9 2006/12/31 16:05:25 tony Exp $
-FHDR-------------------------------------------------------------------
*/ 

#include "config.h"
#include "tcp_ip_cfg.h"
#include "hardware.h"
#include "ethernet.h"
#include "uart0\uart0.h"
#include "ftp_cfg.h"

#include "icmp.h"
#include "arp.h"
#include "udp.h"
#include "tcp.h"


u16 cur_handle_position = 0;
/****************************************************************************
* 名称:socket
* 功能:获得一个空SOCKET
* 入口:protocol--SOCKET类型-(UDP_PROTOCOL 或TCP_PROTOCOL)
* 出口: 返回一个指向空SOCKET的指针,or NULL(failed)
****************************************************************************/

SOCKET * socket(u16 af,u16 type,u16 protocol)
{ u16 i;
  if(protocol == UDP_PROTOCOL)
  {
    for(i = 0;i < MAX_UDP_LINKS;i++)
    {
      if(!UDP_Socket[i].EN)  
            break;
      
    }
   if(i >= MAX_UDP_LINKS)
          return(NULL);
   UDP_Socket[i].EN = 1;
   UDP_Socket[i].PROTOCOL = UDP_PROTOCOL;
   return(&UDP_Socket[i]);
  
  }
  else if(protocol == TCP_PROTOCOL)
  {
    for(i = 0;i < MAX_TCP_LINKS;i++)
    {
      if(!TCP_Socket[i].EN)  
            break;
      
    }
   if(i >= MAX_TCP_LINKS)
          return(NULL);
   TCP_Socket[i].EN = 1;
   TCP_Socket[i].PROTOCOL = TCP_PROTOCOL;
   TCP_Socket[i].type = type;
   return(&TCP_Socket[i]); 
  
  }
  return(NULL);

}

/****************************************************************************
* 名称:bind()
* 功能:将IP地址与SOCKET绑定
* 入口:sock--指向SOCKET的指针
        struct sockaddr--包括IP地址和端口号
        len --无作用
* 出口: SUCC
****************************************************************************/
u16 bind(SOCKET * sock,struct sockaddr * address,u8 len)
{

    sock->SRC_IP_Address[0] = address->sin_addr[0];
    sock->SRC_IP_Address[1] = address->sin_addr[1];
    sock->SRC_IP_Address[2] = address->sin_addr[2];
    sock->SRC_IP_Address[3] = address->sin_addr[3];
    sock->SRC_Port[0] = address->sin_port & 0xff;
    sock->SRC_Port[1] = address->sin_port >> 8;
    return(SUCC);
  

}

/****************************************************************************
* 名称:listen()
* 功能:起动监听
* 入口:sock--指向SOCKET的指针
        QTY --无作用
* 出口: SUCC
****************************************************************************/

u16 listen(SOCKET * sock, u16 QTY)
{
  u16 port;
  port = sock->SRC_Port[0] + sock->SRC_Port[1] * 256;
  if(sock->PROTOCOL == UDP_PROTOCOL)
  {
    enable_a_port_listen(port); 
  }
  else if(sock->PROTOCOL == TCP_PROTOCOL)
   TCP_enable_a_port_listen(port);
   
  return(SUCC);
}

/****************************************************************************
* 名称:connect()
* 功能:客户端连接服务器
* 入口:sock--指向SOCKET的指针
*       struct sockaddr   address--服务器的地址和监听端口号
*       len --无作用(保留为将来扩展使用)
* 出口: 返回SUCC--连接成功 或者-FAIL
****************************************************************************/  
u16 connect(SOCKET * sock, struct sockaddr * sevaddr,u8 len) 
{
 u8 IP[8];
 u8 pkt[100],i;
 u16 index,retry;
 //u16 port;
 //port = Allocate_A_LOCAL_Port();
 // if(port == 0xffff)
 //   return(0xffff);
 for(i = 0;i < 4;i++)
 {
   IP[i+4] = sock->SRC_IP_Address [i];
   IP[i] = sevaddr->sin_addr[i];
   sock->DEST_IP_Address[i] = sevaddr->sin_addr[i];

 }

 pkt[12] = sock->SRC_Port[1];
 pkt[13] = sock->SRC_Port[0];
 pkt[14] = sevaddr->sin_port >>8;  
 pkt[15] = sevaddr->sin_port & 0xff;
 
 sock->DEST_Port[0] = sevaddr->sin_port & 0xff;
 sock->DEST_Port[1] = sevaddr->sin_port >> 8;

 index =  sock - TCP_Socket;  
 retry = 0;
do{   
 if( Send_TCP_SYN_nACK(pkt+12,20,IP,index) == SUCC) 
    {
     SendByte('c');SendByte('c');SendByte('c');SendByte('c');
     
     return(index);
    }
 else
    {SendByte('e');SendByte('e');SendByte('e');SendByte('e');
     retry ++;
     if(retry == 3)
       return(0xffff);
    }
 }while(1);
}


/****************************************************************************
* 名称:listen()
* 功能:起动监听
* 入口:sock--指向SOCKET的指针
        struct sockaddr * address,iii --无作用
* 出口: 返回SOCKET的索引号
****************************************************************************/  
u16 accept(SOCKET * sock,struct sockaddr * address,u16 *iii)
{
  
  u8 flag,j;
  s16 i;

    
   i = cur_handle_position;
   while(1){
   i++;
   if(i>=MAX_TCP_LINKS)
      i = 0;
   if(i == cur_handle_position)
      {cur_handle_position++;
       if(cur_handle_position == MAX_TCP_LINKS)
         cur_handle_position = 0;
       return(0xffff);}
  //for(i = MAX_TCP_LINKS - 1;i >= 0 ;i--)
  //{
      if(sock == (TCP_Socket + i))
         continue;
      if(TCP_Socket[i].EN)
      {   /*检查源端口号*/
          if(TCP_Socket[i].SRC_Port[1] == sock->SRC_Port[1] &&
             TCP_Socket[i].SRC_Port[0] == sock->SRC_Port[0])
          {/*检查源IP地址*/
            flag = SUCC;
            for(j = 0;j < 4;j++)
            {
              if(sock->SRC_IP_Address[j] !=  TCP_Socket[i].SRC_IP_Address[j])
                  {
                    flag = FAIL;
                    break;
                  }
            } 
            if(flag == SUCC)
            {  
               for(j = 0;j < 4;j++)
                 {
                  if(TCP_Socket[i].DEST_IP_Address[j] != 0)
                  {
                    flag = FAIL;
                    break;
                  }
                 }
               if(flag == SUCC)
                 continue;
               if(TCP_Socket[i].status == Closed)
               {
                 TCP_Socket[i].status = Link_established;
                 {cur_handle_position = i;return(i);}
               }
               else if(TCP_Socket[i].status == Data_Transmition_State)
                 {cur_handle_position = i;return(i);}
               else if(Query_Queue_data_available(&TCP_Socket[i]) > 0)
                 {cur_handle_position = i;return(i);}
               else 
                 continue;
            }
            else
            {
                continue;
            }
            
          }
          else
            continue;
 
      }           

 }
     return(0xffff);

}

/****************************************************************************
* 名称:recv()
* 功能:从socket读取数据
* 入口:handle--SOCKET的索引号
        rec_buff--缓冲区的首地址
        len-缓冲区长度
        i --无作用
* 出口: 返回
****************************************************************************/
u16 recv(u16 handle,u8 * rec_buff,u16 len,u16 i)
{
 u16 qty;

 qty = Query_Queue_data_available(&TCP_Socket[handle]);
 if(qty == 0)
   return(0);
 if(len > qty)
   len = qty;
 Queue_GET(&TCP_Socket[handle],rec_buff,len);
 
 return(len);

}

/****************************************************************************
* 名称:send()
* 功能:向socket写入数据
* 入口:handle--SOCKET的索引号
        rec_buff--缓冲区的首地址
        len-缓冲区长度
        i --无作用
* 出口: 返回
****************************************************************************/
u8 send(u16 handle,u8 *rec_buff,u16 len,u16 i)
{
  //u16 retry;
  struct _pkst TxdData;
  TxdData.STPTR = NULL;
  TxdData.length = len ;
  TxdData.DAPTR =rec_buff;
  /*retry = 0;
 do{
   if(Send_TCP_PSH(&TxdData, handle) == SUCC)
      break;
   retry++;
   if( retry > 10)
     return(FAIL);
  }while(1);*/
  Send_TCP_PSH(&TxdData, handle) ;
  return(SUCC); 
}

/****************************************************************************
* 名称:close()
* 功能:关闭一个SOCKET监听
* 入口:handle--SOCKET的索引号
* 出口: 返回
****************************************************************************/
void close(u16 handle)
{
 if(TCP_Socket[handle].EN)
 { 
  TCP_Socket[handle].status = Half_closed;
  Send_TCP_FIN(handle);
 }


}


/****************************************************************************
* 名称:recvform()
* 功能:从socket读数据(for UDP数据报)
* 入口:handle--SOCKET的索引号
        rec_buff--缓冲区的首地址
        len-缓冲区长度
* 出口: 返回
****************************************************************************/
u16 recvfrom(SOCKET *sock,u8 *rec_buff,u16 len,u8 i,struct sockaddr * address,u16 *addr_len)
{
  u16 data_available;
  if(sock->PROTOCOL == UDP_PROTOCOL)
  {
   sock->DEST_IP_Address[0] = address->sin_addr[0];
   sock->DEST_IP_Address[1] = address->sin_addr[1];
   sock->DEST_IP_Address[2] = address->sin_addr[2];
   sock->DEST_IP_Address[3] = address->sin_addr[3];
   sock->DEST_Port[0] =  address->sin_port & 0xff;
   sock->DEST_Port[1] = address->sin_port >> 8;
  
   data_available = Query_Queue_data_available(sock);

   if(len > data_available)
     len = data_available;
   if(len > 0)
    Queue_GET(sock,rec_buff,len); 
   return(len);
  }
  return(SUCC);  
}
/****************************************************************************
* 名称:send()
* 功能:向socket写入数据(for UDP数据报)
* 入口:handle--SOCKET的索引号
        rec_buff--缓冲区的首地址
        len-缓冲区长度
* 出口: 返回
****************************************************************************/

u16 sendto(SOCKET *sock,u8 *rec_buff,u16 len,u8 i,struct sockaddr  * address,u16 *addr_len)
{
  struct _pkst TxdData;  
  if(sock->PROTOCOL == UDP_PROTOCOL)
  {
   
   sock->DEST_IP_Address[0] = address->sin_addr[0];
   sock->DEST_IP_Address[1] = address->sin_addr[1];
   sock->DEST_IP_Address[2] = address->sin_addr[2];
   sock->DEST_IP_Address[3] = address->sin_addr[3];
   sock->DEST_Port[0] =  address->sin_port & 0xff;
   sock->DEST_Port[1] = address->sin_port >> 8;
   TxdData.STPTR = NULL;
   TxdData.length = len;
   TxdData.DAPTR = rec_buff;
   Send_UDP_PKT(&TxdData,sock);
  }
  
  return(len);
}


/*
+FFTR--------------------------------------------------------------------
$Log: socket.c,v $
Revision 1.9  2006/12/31 16:05:25  tony
增加了WEB服务器的功能,运行效果好

Revision 1.8  2006/12/31 23:03:39  tony
解决了DATA abort的bug,是由ftp.c调用函数accept造成的,因此给其加入一个循环,直到accept()返回值不为0xffff,结束

Revision 1.7  2006/12/31 17:49:37  tony
解决了写小文件的hang问题,但有data_abort错误,待解决
 
Revision 1.6  2006/12/31 16:09:00  tony
由于write_file慢(1KB/S)导致FTP服务器put file失序,不写file时序正常

Revision 1.5  2007/01/01 00:11:31  tony
完成了与FTP.EXE兼容,如命令dir,ls,get;
与IE(Internet Explorer)已完成了目录查看,
拷贝小于80k的文件

Revision 1.4  2007/01/01 14:53:47  tony
FTP 实现了拷贝文件的功能,

Revision 1.3  2006/12/31 16:12:54  tony
SOCKET API函数connect()测试成功

Revision 1.2  2006/12/31 16:04:53  tony
增加FTP代码,SOCKET_status字段


-FFTR--------------------------------------------------------------------
*/






⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -