?? socket.c
字號:
//************************************SOCKET.C**************************************
//
// 應(yīng)用層操作
//
// 1. 主動建立SOCKET,調(diào)用SOCKET_CREATE
// 2. 關(guān)閉SOCKET,調(diào)用SOCKET_DELETE
// 3. 讀SOCKET輸入緩沖區(qū),調(diào)用SOCKET_READ_INBUFFER
// 4. 寫SOCKET輸出緩沖區(qū),調(diào)用SOCKET_WRITE_OUTBUFFER
// 5. 創(chuàng)建監(jiān)聽某個(gè)端口的SOCKET,調(diào)用SOCKET_CREATE_LISTEN(unsigned int PORT_NUM)
// TCP層對SOCKET的操作
//
// 1. 關(guān)閉SOCKET(也就是來自遠(yuǎn)程PC的關(guān)閉命令) SOCKET_DELETE()
// 2. 向SOCKET的輸入緩沖寫入接收到的來自遠(yuǎn)程PC的數(shù)據(jù) SOCKET_WRITE_INBUFFER
// 3. 讀取SOCKET輸出緩沖區(qū)中的數(shù)據(jù)調(diào)用 SOCKET_READ_OUTBUFFER(unsigned char *dest_addr,len)
// 返回實(shí)際讀取的數(shù)據(jù)長度
//
// SOCKET數(shù)據(jù)結(jié)構(gòu):參見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];
//***************************************************
// 由上層應(yīng)用層調(diào)用
// 返回連接的號
// 如果沒有連接可用了,則返回的是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; //這里應(yīng)該是緩沖區(qū)的總長度,而不是數(shù)據(jù)長度
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; //最大接收緩存區(qū)
conxn[nr].my_sequence = initial_sequence_nr;
initial_sequence_nr += 64000;
conxn[nr].flags = FLG_SYN; //這里將標(biāo)志置為SYN,則在TCP_TICK中將發(fā)送連接請求
//tcp_send(FLG_SYN,28,nr); //發(fā)動了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; //這里只發(fā)送FIN標(biāo)志,真正的關(guān)閉是在TCP,TCP_TICK在發(fā)送完FIN后要將連接的狀態(tài)置為STATE_FIN_WAIT_1
//conxn[nr].state = STATE_FIN_WAIT_1;
}
//*******************************************
void SOCKET_RESET(unsigned char nr)
{
conxn[nr].flags = FLG_RST; //這里只發(fā)送RST標(biāo)志,TCP_TICK在發(fā)送完RST后要將連接的狀態(tài)置為STATE_CLOSED
}
//**********************************************************************************************************
// 這是由應(yīng)用層調(diào)用的,它讓一個(gè)空閑的連接等待遠(yuǎn)程PC的連接,
// 當(dāng)TCP有被動連接請求時(shí),首先要看有無連接在LISTEN這個(gè)端口
// 如果沒有正在LISTEN的連接則說明此請求是無效的。
//
// 找一個(gè)空閑連接,在此等待特定端口的連接建立
//
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; //在這個(gè)端口等,例如:HTTP 80
conxn[nr].local_window = max_socket_in_len; //最大接收緩存區(qū)
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];
}
//***************************************************************
// 上層應(yīng)用程序每隔一段時(shí)間檢查一下連接,看有無數(shù)據(jù)過來,如果有
// 則將其放入指定的區(qū)域。
// 返回:本次讀取到的數(shù)據(jù)的長度
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]; //全部讀到上層指定的內(nèi)存中去
CN->inbuf_head++;
CN->inbuf_head &= max_mm;
}
}
else
{
while(CN->inbuf_head != CN->inbuf_tail)
{
*(buf+i) = CN->inbuf[CN->inbuf_head]; //全部讀到上層指定的內(nèi)存中去
i++;
CN->inbuf_head++;
CN->inbuf_head &= max_mm;
}
}
// CN->flags &= ~FLG_WIN_ZERO;//清掉窗口為0的標(biāo)志
CN->local_window = max_socket_in_len; //恢復(fù)窗口的最大尺寸。
return i;
}
//***************************************************************
//
// 向SOCKET寫入數(shù)據(jù),在TCP_TICK中不停掃描,如果發(fā)現(xiàn)數(shù)據(jù)長度不是0,則發(fā)送出去。
// 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; //還沒有傳送完成 ,說明接收的太快,無法轉(zhuǎn)送出去
memcpy(CN->outbuf,from,len);
CN->offset = 0;
CN->outbuf_len = len; //當(dāng)TCP傳完后將outbuf_len清零
CN->flags = FLG_PSH; //送數(shù)據(jù)
if(CN->local_window != 0)
CN->flags &= ~FLG_WIN_ZERO;//清掉窗口為0的標(biāo)志
return 0;
}
//***************************************************************
// 看寫到SOCKET去的數(shù)據(jù)是否已經(jīng)被對方收到,也就是收到了對方的ACK
// 0 表示已經(jīng)收到了 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;
}
//***************************************************************
// 設(shè)置窗口大小
void SOCKET_SET_WIN(CONNECTION *CN,unsigned int size)
{
CN->local_window = size;
}
//檢查連接的輸出緩沖區(qū)數(shù)據(jù)的長度
unsigned int SOCKET_GET_O_L(CONNECTION *CN)
{
return CN->outbuf_len; //輸出緩沖區(qū)數(shù)據(jù)的長度
}
//查看連接的輸入緩沖區(qū)數(shù)據(jù)的長度
unsigned int SOCKET_GET_IN_L(CONNECTION *CN)
{
if(CN->inbuf_head != CN->inbuf_tail) return 1;
if(CN->local_window ==0) return 1; //緩沖區(qū)滿了
return 0; //輸出緩沖區(qū)數(shù)據(jù)的長度
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -