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

📄 socket.c

📁 完整的TCP/IP源代码,绝对好用
💻 C
字号:

//************************************SOCKET.C**************************************
//
// 应用层操作
//
// 1. 主动建立SOCKET,调用SOCKET_CREATE
// 2. 关闭SOCKET,调用SOCKET_DELETE
// 3. 读SOCKET输入缓冲区,调用SOCKET_READ_INBUFFER
// 4. 写SOCKET输出缓冲区,调用SOCKET_WRITE_OUTBUFFER
// 5. 创建监听某个端口的SOCKET,调用SOCKET_CREATE_LISTEN(unsigned int PORT_NUM)

// TCP层对SOCKET的操作
//
// 1. 关闭SOCKET(也就是来自远程PC的关闭命令) SOCKET_DELETE()
// 2. 向SOCKET的输入缓冲写入接收到的来自远程PC的数据 SOCKET_WRITE_INBUFFER
// 3. 读取SOCKET输出缓冲区中的数据调用 SOCKET_READ_OUTBUFFER(unsigned char *dest_addr,len)
//    返回实际读取的数据长度
// 
// SOCKET数据结构:参见TCP.c文件
// 
//

//***************************************************************************************************************

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "C:\wql\tcpipsocket\tcp.h"
#include "c:\wql\tcpipsocket\tcp.c"
#include "C:\wql\tcpipsocket\ip.c"
#include "C:\wql\tcpipsocket\arp.c"
#include "C:\wql\tcpipsocket\icmp.c"

extern UINT32 initial_sequence_nr;
extern CONNECTION xdata conxn[MAX_SOCKET_NUM];
//***************************************************
// 由上层应用层调用
// 返回连接的号
// 如果没有连接可用了,则返回的是NO_CONNECTION
//***************************************************
CONNECTION *SOCKET_CREATE(unsigned int dest_port,unsigned char *dest_ip,unsigned int local_port,unsigned char *outbuf)
{
  unsigned char nr;

  nr = find_leisure_connection();
  if (nr == NO_CONNECTION) return NULL;
  conxn[nr].outbuf = outbuf;
  //conxn[nr].outbuf_len = outbuf_len; //这里应该是缓冲区的总长度,而不是数据长度
  conxn[nr].outbuf_len = 0;

  conxn[nr].port = dest_port;
  conxn[nr].local_port = local_port;
  conxn[nr].ipaddr[0] = *dest_ip;
  conxn[nr].ipaddr[1] = *(dest_ip+1);
  conxn[nr].ipaddr[2] = *(dest_ip+2);
  conxn[nr].ipaddr[3] = *(dest_ip+3);
  conxn[nr].local_window = max_socket_in_len; //最大接收缓存区
  conxn[nr].my_sequence = initial_sequence_nr;
  initial_sequence_nr += 64000;
  conxn[nr].flags = FLG_SYN;       //这里将标志置为SYN,则在TCP_TICK中将发送连接请求
  //tcp_send(FLG_SYN,28,nr);                   //发动了TCP连接
  conxn[nr].state   = STATE_ACT_SYN_SENT;
  conxn[nr].timer   = TCP_TIMEOUT;                     //2 second
  conxn[nr].inactivity   = INACTIVITY_TIME;
  return &conxn[nr];
}
//*******************************************
void SOCKET_DELETE(CONNECTION *CN)
{
  CN -> flags = FLG_FIN; //这里只发送FIN标志,真正的关闭是在TCP,TCP_TICK在发送完FIN后要将连接的状态置为STATE_FIN_WAIT_1
  //conxn[nr].state = STATE_FIN_WAIT_1;

}
//*******************************************
void SOCKET_RESET(unsigned char nr)
{
  conxn[nr].flags = FLG_RST; //这里只发送RST标志,TCP_TICK在发送完RST后要将连接的状态置为STATE_CLOSED
}

//**********************************************************************************************************
// 这是由应用层调用的,它让一个空闲的连接等待远程PC的连接,
// 当TCP有被动连接请求时,首先要看有无连接在LISTEN这个端口
// 如果没有正在LISTEN的连接则说明此请求是无效的。
//
// 找一个空闲连接,在此等待特定端口的连接建立
// 
CONNECTION * SOCKET_CREATE_LISTEN(unsigned int PORT_NUM,unsigned char *outbuf)
{
  unsigned char nr;

  nr = find_leisure_connection();
  if (nr == NO_CONNECTION) return NULL;
  conxn[nr].local_port = PORT_NUM;   //在这个端口等,例如:HTTP 80
  conxn[nr].local_window = max_socket_in_len; //最大接收缓存区
  conxn[nr].state   = STATE_LISTEN;
  conxn[nr].timer = TCP_TIMEOUT;
  conxn[nr].inactivity = INACTIVITY_TIME;
  conxn[nr].outbuf = outbuf;
  conxn[nr].outbuf_len = 0;
  return &conxn[nr];
}
//***************************************************************
// 上层应用程序每隔一段时间检查一下连接,看有无数据过来,如果有
// 则将其放入指定的区域。
// 返回:本次读取到的数据的长度

unsigned int SOCKET_READ_INBUFFER(CONNECTION *CN, unsigned char *buf)
{
  unsigned int i;
  i=0;
  if(CN->local_window==0) //满了
  {
    for(i=0;i<256;i++)
    {
      *(buf+i) = CN->inbuf[CN->inbuf_head];	//全部读到上层指定的内存中去
	  CN->inbuf_head++;
	  CN->inbuf_head &= max_mm;
    }
  }
  else
  {
    while(CN->inbuf_head != CN->inbuf_tail)
    {
      *(buf+i) = CN->inbuf[CN->inbuf_head];	//全部读到上层指定的内存中去
	  i++;
	  CN->inbuf_head++;
	  CN->inbuf_head &= max_mm;
    }
 
  }
//  CN->flags &= ~FLG_WIN_ZERO;//清掉窗口为0的标志
  CN->local_window = max_socket_in_len; //恢复窗口的最大尺寸。

  return i;
}

//***************************************************************
//
// 向SOCKET写入数据,在TCP_TICK中不停扫描,如果发现数据长度不是0,则发送出去。
// CN -socket 
// from -- source addr
// len  -- data length
//
// return 1=error(失败) 0 = normal(成功)
//***************************************************************

unsigned char SOCKET_WRITE_OUTBUFFER(CONNECTION *CN,unsigned char *from,unsigned int len )
{
  if(CN->state != STATE_ESTABLISHED) return 1;
  if(CN->outbuf_len != 0) return 1;  //还没有传送完成 ,说明接收的太快,无法转送出去

  memcpy(CN->outbuf,from,len);
  CN->offset = 0;
  CN->outbuf_len = len; //当TCP传完后将outbuf_len清零
  CN->flags = FLG_PSH;  //送数据

  if(CN->local_window != 0)
     CN->flags &= ~FLG_WIN_ZERO;//清掉窗口为0的标志

  return 0;

}

//***************************************************************
// 看写到SOCKET去的数据是否已经被对方收到,也就是收到了对方的ACK
// 0 表示已经收到了 1表示没有收到 2表示连接没有建立 
unsigned char SOCKET_WRITE_END(CONNECTION *CN)
{
  if(CN->state != STATE_ESTABLISHED) return 2;
  if(CN->outbuf_len != 0) return 1;  //还没有传送完成 

  if(CN->his_ack == CN->my_sequence) return 0;
  return 1;
}
//***************************************************************
// 设置窗口大小
void SOCKET_SET_WIN(CONNECTION *CN,unsigned int size)
{
  CN->local_window = size;
}
//检查连接的输出缓冲区数据的长度
unsigned int SOCKET_GET_O_L(CONNECTION *CN)
{
  return CN->outbuf_len; //输出缓冲区数据的长度
}
//查看连接的输入缓冲区数据的长度
unsigned int SOCKET_GET_IN_L(CONNECTION *CN)
{
  if(CN->inbuf_head != CN->inbuf_tail) return 1;
  if(CN->local_window ==0) return 1; //缓冲区满了
  return 0; //输出缓冲区数据的长度
}


⌨️ 快捷键说明

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