示例程序,转载自CNBLOG,做了针对C语言编译器的适应性修正:
#include <stdio.h>#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib") /* WinSock使用的库函数 */
/* 定义常量 */
#define HTTP_DEF_PORT 80 /* 连接的缺省端口 */
#define HTTP_BUF_SIZE 1024 /* 缓冲区的大小 */
#define HTTP_HOST_LEN 256 /* 主机名长度 */
char *http_req_hdr_tmpl = "GET %s HTTP/1.1\r\n"
"Accept: image/gif, image/jpeg, */*\r\nAccept-Language: zh-cn\r\n"
"Accept-Encoding: gzip, deflate\r\nHost: %s:%d\r\n"
"User-Agent: Huiyong's Browser <0.1>\r\nConnection: Keep-Alive\r\n\r\n"
/**************************************************************************
*
* 函数功能: 解析命令行参数, 分别得到主机名, 端口号和文件名. 命令行格式:
* [http://www.baidu.com:8080/index.html]
*
* 参数说明: [IN] buf, 字符串指针数组
* 带册 [OUT] host, 保存主机
* [OUT] port, 端口
* [OUT] file_name, 文件名
*
* 返 回 值: void.
*
**************************************************************************/
void http_parse_request_url(const char *buf, char *host,
陆行做 unsigned short *port, char *file_name)
{
int length = 0
char port_buf[8]
char *buf_end = (char *)(buf + strlen(buf))
char *begin, *host_end, *colon, *file
/* 查找主机的开始位置 */
begin = (char*)(strstr(buf, "//"))
begin = (begin ? begin + 2 : (char*)(buf))
colon = strchr(begin, ':')
早衡host_end = strchr(begin, '/')
if (host_end == NULL)
{
host_end = buf_end
}
else
{ /* 得到文件名 */
file = strrchr(host_end, '/')
if (file && (file + 1) != buf_end)
strcpy(file_name, file + 1)
}
if (colon) /* 得到端口号 */
{
colon++
length = host_end - colon
memcpy(port_buf, colon, length)
port_buf[length] = 0
*port = atoi(port_buf)
host_end = colon - 1
}
/* 得到主机信息 */
length = host_end - begin
memcpy(host, begin, length)
host[length] = 0
}
int main(int argc, char **argv)
{
WSADATA wsa_data
SOCKET http_sock = 0 /* socket 句柄 */
struct sockaddr_in serv_addr /* 服务器地址 */
struct hostent *host_ent
int result = 0, send_len
char data_buf[HTTP_BUF_SIZE]
char host[HTTP_HOST_LEN] = "127.0.0.1"
unsigned short port = HTTP_DEF_PORT
unsigned long addr
char file_name[HTTP_HOST_LEN] = "index.html"
char file_nameforsave[HTTP_HOST_LEN] = "index1.html"
FILE *file_web
if (argc != 2)
{
printf("[Web] input : %s http://www.test.com[:8080]/index.html", argv[0])
return -1
}
http_parse_request_url(argv[1], host, &port, file_name)
WSAStartup(MAKEWORD(2,0), &wsa_data) /* 初始化 WinSock 资源 */
addr = inet_addr(host)
if (addr == INADDR_NONE)
{
host_ent = gethostbyname(host)
if (!host_ent)
{
printf("[Web] invalid host\n")
return -1
}
memcpy(&addr, host_ent->h_addr_list[0], host_ent->h_length)
}
/* 服务器地址 */
serv_addr.sin_family = AF_INET
serv_addr.sin_port = htons(port)
serv_addr.sin_addr.s_addr = addr
http_sock = socket(AF_INET, SOCK_STREAM, 0) /* 创建 socket */
result = connect(http_sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr))
if (result == SOCKET_ERROR) /* 连接失败 */
{
closesocket(http_sock)
printf("[Web] fail to connect, error = %d\n", WSAGetLastError())
return -1
}
/* 发送 HTTP 请求 */
send_len = sprintf(data_buf, http_req_hdr_tmpl, argv[1], host, port)
result = send(http_sock, data_buf, send_len, 0)
if (result == SOCKET_ERROR) /* 发送失败 */
{
printf("[Web] fail to send, error = %d\n", WSAGetLastError())
return -1
}
file_web = fopen(file_nameforsave, "a+")
do /* 接收响应并保存到文件中 */
{
result = recv(http_sock, data_buf, HTTP_BUF_SIZE, 0)
if (result > 0)
{
fwrite(data_buf, 1, result, file_web)
/* 在屏幕上输出 */
data_buf[result] = 0
printf("%s", data_buf)
}
} while(result > 0)
fclose(file_web)
closesocket(http_sock)
WSACleanup()
return 0
}
实现步骤:1)用Wireshark软件抓包得到test.pcap文件
2)程序:分析pcap文件头 ->分析pcap_pkt头 ->分析帧头 ->分析ip头 ->分析tcp头 ->分析http信息
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<netinet/in.h>
#include<time.h>
#define BUFSIZE 10240
#define STRSIZE 1024
typedef long bpf_int32
typedef unsigned long bpf_u_int32
typedef unsigned short u_short
typedef unsigned long u_int32
typedef unsigned short u_int16
typedef unsigned char u_int8
//pacp文件头结构体
struct pcap_file_header
{
bpf_u_int32 magic /* 0xa1b2c3d4 */
u_short version_major /* magjor Version 2 */
u_short version_minor /* magjor Version 4 */
bpf_int32 thiszone /* gmt to local correction */
bpf_u_int32 sigfigs/* accuracy of timestamps */
bpf_u_int32 snaplen/* max length saved portion of each pkt */
bpf_u_int32 linktype /* data link type (LINKTYPE_*) */
}
//时间戳
struct time_val
{
long tv_sec/* seconds 含义同 time_t 对象的值 */
long tv_usec /* and microseconds */
}
//pcap数据包头结构体
struct pcap_pkthdr
{
struct time_val ts /* time stamp */
bpf_u_int32 caplen/* length of portion present */
bpf_u_int32 len /* length this packet (off wire) */
}
//数据帧头
typedef struct FramHeader_t
{ //Pcap捕获的数据帧头
u_int8 DstMAC[6] //目的MAC地址
u_int8 SrcMAC[6] //源MAC地址
u_short FrameType //帧类型
} FramHeader_t
//IP数据报头
typedef struct IPHeader_t
{ //IP数据报头
u_int8 Ver_HLen //版本+报头长度
u_int8 TOS //服务类型
u_int16 TotalLen //总长度
u_int16 ID //标识
u_int16 Flag_Segment //标志+片偏移
u_int8 TTL //生存周期
u_int8 Protocol //协议类型
u_int16 Checksum //头部校验和
u_int32 SrcIP //源IP地址
u_int32 DstIP //目的IP地址
} IPHeader_t
//TCP数据州返报头
typedef struct TCPHeader_t
{ //TCP数据报头
u_int16 SrcPort //源端口
u_int16 DstPort //目的端口
u_int32 SeqNO //序号肆迹早
u_int32 AckNO //确认号
u_int8 HeaderLen //数据报头的长裂雀度(4 bit) + 保留(4 bit)
u_int8 Flags //标识TCP不同的控制消息
u_int16 Window //窗口大小
u_int16 Checksum //校验和
u_int16 UrgentPointer //紧急指针
}TCPHeader_t
//
void match_http(FILE *fp, char *head_str, char *tail_str, char *buf, int total_len) //查找 http 信息函数
//
int main()
{
struct pcap_file_header *file_header
struct pcap_pkthdr *ptk_header
IPHeader_t *ip_header
TCPHeader_t *tcp_header
FILE *fp, *output
int pkt_offset, i=0
int ip_len, http_len, ip_proto
int src_port, dst_port, tcp_flags
char buf[BUFSIZE], my_time[STRSIZE]
char src_ip[STRSIZE], dst_ip[STRSIZE]
char host[STRSIZE], uri[BUFSIZE]
//初始化
file_header = (struct pcap_file_header *)malloc(sizeof(struct pcap_file_header))
ptk_header = (struct pcap_pkthdr *)malloc(sizeof(struct pcap_pkthdr))
ip_header = (IPHeader_t *)malloc(sizeof(IPHeader_t))
tcp_header = (TCPHeader_t *)malloc(sizeof(TCPHeader_t))
memset(buf, 0, sizeof(buf))
//
if((fp = fopen(“test.pcap”,”r”)) == NULL)
{
printf(“error: can not open pcap file\n”)
exit(0)
}
if((output = fopen(“output.txt”,”w+”)) == NULL)
{
printf(“error: can not open output file\n”)
exit(0)
}
//开始读数据包
pkt_offset = 24 //pcap文件头结构 24个字节
while(fseek(fp, pkt_offset, SEEK_SET) == 0) //遍历数据包
{
i++
//pcap_pkt_header 16 byte
if(fread(ptk_header, 16, 1, fp) != 1) //读pcap数据包头结构
{
printf(“\nread end of pcap file\n”)
break
}
pkt_offset += 16 + ptk_header->caplen //下一个数据包的偏移值
strftime(my_time, sizeof(my_time), “%Y-%m-%d %T”, localtime(&(ptk_header->ts.tv_sec))) //获取时间
// printf(“%d: %s\n”, i, my_time)
//数据帧头 14字节
fseek(fp, 14, SEEK_CUR) //忽略数据帧头
//IP数据报头 20字节
if(fread(ip_header, sizeof(IPHeader_t), 1, fp) != 1)
{
printf(“%d: can not read ip_header\n”, i)
break
}
inet_ntop(AF_INET, (void *)&(ip_header->SrcIP), src_ip, 16)
inet_ntop(AF_INET, (void *)&(ip_header->DstIP), dst_ip, 16)
ip_proto = ip_header->Protocol
ip_len = ip_header->TotalLen //IP数据报总长度
// printf(“%d: src=%s\n”, i, src_ip)
if(ip_proto != 0×06) //判断是否是 TCP 协议
{
continue
}
//TCP头 20字节
if(fread(tcp_header, sizeof(TCPHeader_t), 1, fp) != 1)
{
printf(“%d: can not read ip_header\n”, i)
break
}
src_port = ntohs(tcp_header->SrcPort)
dst_port = ntohs(tcp_header->DstPort)
tcp_flags = tcp_header->Flags
// printf(“%d: src=%x\n”, i, tcp_flags)
if(tcp_flags == 0×18) // (PSH, ACK) 3路握手成功后
{
if(dst_port == 80) // HTTP GET请求
{
http_len = ip_len – 40 //http 报文长度
match_http(fp, “Host: “, “\r\n”, host, http_len) //查找 host 值
match_http(fp, “GET “, “HTTP”, uri, http_len) //查找 uri 值
sprintf(buf, “%d: %s src=%s:%d dst=%s:%d %s%s\r\n”, i, my_time, src_ip, src_port, dst_ip, dst_port, host, uri)
//printf(“%s”, buf)
if(fwrite(buf, strlen(buf), 1, output) != 1)
{
printf(“output file can not write”)
break
}
}
}
} // end while
fclose(fp)
fclose(output)
return 0
}
//查找 HTTP 信息
void match_http(FILE *fp, char *head_str, char *tail_str, char *buf, int total_len)
{
int i
int http_offset
int head_len, tail_len, val_len
char head_tmp[STRSIZE], tail_tmp[STRSIZE]
//初始化
memset(head_tmp, 0, sizeof(head_tmp))
memset(tail_tmp, 0, sizeof(tail_tmp))
head_len = strlen(head_str)
tail_len = strlen(tail_str)
//查找 head_str
http_offset = ftell(fp) //记录下HTTP报文初始文件偏移
while((head_tmp[0] = fgetc(fp)) != EOF) //逐个字节遍历
{
if((ftell(fp) – http_offset) >total_len) //遍历完成
{
sprintf(buf, “can not find %s \r\n”, head_str)
exit(0)
}
if(head_tmp[0] == *head_str) //匹配到第一个字符
{
for(i=1i<head_leni++) //匹配 head_str 的其他字符
{
head_tmp[i]=fgetc(fp)
if(head_tmp[i] != *(head_str+i))
break
}
if(i == head_len) //匹配 head_str 成功,停止遍历
break
}
}
// printf(“head_tmp=%s \n”, head_tmp)
//查找 tail_str
val_len = 0
while((tail_tmp[0] = fgetc(fp)) != EOF) //遍历
{
if((ftell(fp) – http_offset) >total_len) //遍历完成
{
sprintf(buf, “can not find %s \r\n”, tail_str)
exit(0)
}
buf[val_len++] = tail_tmp[0] //用buf 存储 value 直到查找到 tail_str
if(tail_tmp[0] == *tail_str) //匹配到第一个字符
{
for(i=1i<tail_leni++) //匹配 head_str 的其他字符
{
tail_tmp[i]=fgetc(fp)
if(tail_tmp[i] != *(tail_str+i))
break
}
if(i == tail_len) //匹配 head_str 成功,停止遍历
{
buf[val_len-1] = 0 //清除多余的一个字符
break
}
}
}
// printf(“val=%s\n”, buf)
fseek(fp, http_offset, SEEK_SET) //将文件指针 回到初始偏移
}
C语言编写一个通讯录管理系统的源代码如下:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
/*定义保存通迅录的信息*/
structfriends
{
charname[20]/*名字*/
charprovince[20]/*省份*/
charcity[20]/*所在城市*/
charnation[20]/*民族*/
charsex[2]/*性别M/F*/
intage/*年龄*/
}
扩展资料
1、在芦拿哪C++中应该使用inline内连函数替代宏调用,这样陪码既可达到宏调用的目的,又避免了宏调用的弊端敏橘。
2、在C语言两个函数的名称不能相同,否则会导致编译错误。在C++中,函数名相同而参数不同的两个函数被解释为重载。
3、在大型程序中,使函数名易于管理和使用,不必绞尽脑汁地去处理函数名。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)