这是一个关于socket的题:要求你自己写一个socket程序,然后解析客户端从浏览器地址栏提交的数据。
要求:在浏览器中输入http://localhost:8500 后,你的socket程序向浏览器返回一个网页,以后就用这个网页向你写得这个socket程序提交数据,你的socket程序负责解析这些数据关回答到那个网页上去。
涉及的知识点:1. socket编程; 2.http请求与响应;
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/wait.h>
#include<sys/fcntl.h>
#define PORT 8500//端口号
#define BACKLOG 5/*最大监听数*/
int main(){
char* trim(char* str);
int sockfd,new_fd;/*sockfd是监听套接字,new_fd是通信套接字*/
struct sockaddr_in my_addr;/*本方地址信息结构体,下面有具体的属性赋值*/
struct sockaddr_in their_addr;/*对方地址信息*/
socklen_t sin_size;
char mybuf_1[520] = { 0 };//本socket要返回给网页的信息
char* get_value[10];
sockfd=socket(AF_INET,SOCK_STREAM,0);//获得监听套接字
if(sockfd==-1){
printf("socket failed:%d",errno);
return -1;
}
my_addr.sin_family=AF_INET;/*协议簇*/
my_addr.sin_port=htons(PORT);/*端口号*/
my_addr.sin_addr.s_addr=htonl(INADDR_ANY);/*IP,括号内容表示本机IP*/
bzero(&(my_addr.sin_zero),8);/*将其他属性置0*/
if(bind(sockfd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr))<0){//绑定地址结构体和socket
printf("bind error");
return -1;
}
listen(sockfd,BACKLOG);//开启监听 ,第二个参数是最大监听数
int number = 0;
while(1){
sin_size=sizeof(struct sockaddr_in);
new_fd=accept(sockfd,(struct sockaddr*)&their_addr,&sin_size);//在这里阻塞知道接收到消息,参数分别是socket句柄,接收到的地址信息以及大小
if(new_fd==-1){
printf("receive failed");
}
else {
char request[1024];
recv(new_fd, request, 1024, 0);
request[strlen(request) + 1] = '\0';
printf("%s", request);
printf("网页请求数据接收成功!\n");
//如果是第一次接受请求,就向网页发送响应网址exec.html
//number 代表网页发请求的次数
if (number == 0) {
//char buf[520] = "HTTP/1.1 200 ok\r\nconnection: close\r\n\r\n";//HTTP响应
char buf[520] = "HTTP/1.1 200 ok\r\n\r\n";//HTTP响应
int s = send(new_fd, buf, strlen(buf), 0);//发送响应
int f1 = open("exec.html", O_RDONLY);//消息体
sendfile(new_fd, f1, NULL, 2500);//零拷贝发送消息体
close(f1);
close(new_fd);
}
else {
int m = 0;
/*下面是我对请求协议的解析*/
char* p1 = NULL;//p1代表获取到的网页请求信息中第一行
p1 = strtok(request, "\r\n"); //p1的结果是: GET /?aaa=18&b=99 HTTP/1.1
char* p2 = NULL;//p2代表网页请求信息中的第二行,即网址部分,应该是以空格分割的第二个数据
p2 = strtok(p1, " ");
while (p2 != NULL) {
if (m == 1) {
break;
}
p2 = strtok(NULL, " ");
m++;
}
printf("%s\n", p2); // p2的结果要么是 / ,要么是 /?aaa=18&b=99
char* p3 = NULL;//请求网址中的变量部分
p2 = trim(p2); //去除p2前后的空格
if (strcmp(p2, "/") == 0) {
strcpy(mybuf_1, "请输入get数据\n");
char buf[520] = "HTTP/1.1 200 ok\r\n\r\n";//HTTP响应
int s = send(new_fd, buf, strlen(buf), 0);//发送响应
int s1 = send(new_fd, mybuf_1, strlen(mybuf_1), 0);//发送响应
close(new_fd);
}
else {
p3 = strtok(p2, "?");
m = 0;
while (p3 != NULL) {
if (m == 1) {
break;
}
p3 = strtok(NULL, "?");
m++;
}
printf("%s\n", p3); // 得到的数据是这样的形式: aaa=18&b=99
//下面是对aaa=18&b=99这样的数据用&进行拆分
char* v[15];
char* p4 = NULL;
m = 0;
if (p3 != NULL) {
p4 = strtok(p3, "&");
while (p4) {
v[m] = p4;
++m;
p4 = strtok(NULL, "&");
}
}
printf("共get了%d个参数\n", m);
printf("以下是get提交的数据,分别取出来后存放在get_value[]中\n");
int j;
int z = 0;
for (j = 0; j < m; ++j)
{
printf("v数组的数据是:%s\n", v[j]);
char* p5 = NULL;
if (v[j] != NULL) {
p5 = strtok(v[j], "=");
while (p5) {
get_value[z] = p5;
++z;
p5 = strtok(NULL, "=");
}
}
}
printf("get_value的数据分别是:\n");
for (j = 0; j < z; j++) {
printf("%s\n", get_value[j]);
}
printf("get_value[1]= %s\n", get_value[1]);
if (strcmp(get_value[1], "cat+test") == 0) {
char buf[520] = "HTTP/1.1 200 ok\r\n\r\n";//HTTP响应
int s = send(new_fd, buf, strlen(buf), 0);//发送响应
int f1 = open("test.txt", O_RDONLY);//消息体
sendfile(new_fd, f1, NULL, 2500);//零拷贝发送消息体
close(f1);
close(new_fd);
}
else {
/*把数字转成字符串时,不能用itoa(),linux C它不认*/
char buf[520] = "HTTP/1.1 200 ok\r\n\r\n";//HTTP响应
int s = send(new_fd, buf, strlen(buf), 0);//发送响应
char* buffer = get_value[1];
//strcat(mybuf_1, buffer);
strcpy(mybuf_1, buffer);
int s1 = send(new_fd, mybuf_1, strlen(mybuf_1), 0);//发送响应
close(new_fd);
//下面是把数字转成字符串。不能用itoa(),因为linux c不认
//char buffer[12] = { 0 };
//snprintf(buffer, 3, "%d", number);
//strcat(mybuf_1, buffer);
}
}
}
}
number++;
}
return 0;
}
//去除尾部空格
char* rtrim(char* str)
{
if (str == NULL || *str == '\0')
{
return str;
}
int len = strlen(str);
char* p = str + len - 1;
while (p >= str && isspace(*p))
{
*p = '\0';
--p;
}
return str;
}
//去除首部空格
char* ltrim(char* str)
{
if (str == NULL || *str == '\0')
{
return str;
}
int len = 0;
char* p = str;
while (*p != '\0' && isspace(*p))
{
++p;
++len;
}
memmove(str, p, strlen(str) - len + 1);
return str;
}
//去除首尾空格
char* trim(char* str)
{
char* rtrim(char* str);
char* ltrim(char* str);
str = rtrim(str);
str = ltrim(str);
return str;
}