📄 socket.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 + -