linux c 使用socket处理HTTP请求

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>

#define BUFSIZE 4096 

int main(int argc, char **argv) {

	int sockfd;
	struct sockaddr_in servaddr;
	charhttpRequest[BUFSIZE], buf[BUFSIZE];

	bzero(httpRequest, sizeof(httpRequest));
	
	//构建请求信息,这里请求http://192.168.2.184:8090/test.flv,这是一个由ffserver搭建的流媒体服务
	strcat(httpRequest, "GET /test.flv HTTP/1.1\n");
	strcat(httpRequest, "Host: 192.168.2.184:8090\n");
	strcat(httpRequest, "User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:23.0) Gecko/20100101 Firefox/23.0\n");
	strcat(httpRequest, "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\n");
	strcat(httpRequest, "Accept-Language: en-US,en;q=0.5\n");
	strcat(httpRequest, "Accept-Encoding: gzip, deflate\n");
	//注意这里必须是2个"\n"
	strcat(httpRequest, "Connection: keep-alive\n\n");

        //http请求只支持tcp协议
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sockfd < 0) {
		fprintf(stderr, "create socket error\n");
		exit(1);
	}

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(PORT);
	if(inet_pton(AF_INET, IPSTR, &servaddr.sin_addr) <= 0) {
		fprintf(stderr, "inet_pton error\n");
                close(sockfd);
		exit(1);
	}
	
	if(connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {
		fprintf(stderr, "connect error\n");
                close(sockfd);
		exit(1);
	}

	fprintf(stderr, "connect OK\n");
	fprintf(stderr, "httpRequest: %s\n",httpRequest);

        //发送请求
	int ret = write(sockfd,httpRequest, strlen(httpRequest));	
	if(ret < 0) {
		fprintf(stderr, "write error\n");
                close(sockfd);
		exit(1);
	}

	fprintf(stderr, "writen: %d\n", ret);

        //设置select的超时时间3S
        struct timeval tv;

	fd_set fdSet;

	//TODO: 接收数据,需要处理接收完成等
	while(true) {
                //因为select返回后tv的值是未定义的,所以每次需要重设一下
		tv.tv_sec = 3;
                tv.tv_usec = 0;

	        FD_ZERO(&fdSet);
	        FD_SET(sockfd, &fdSet);
		//这里的第5个参数指定超时时间
		int status = select(sockfd + 1, &fdSet, NULL, NULL, &tv);
                if(status > 0 && FD_ISSET(sockfd, &fdSet)) {
        
           	        memset(buf, 0, 4096);
			int i = read(sockfd, buf, 4096);

			//TODO:需要判断服务器是否返回了正确的状态等
			#if 1
			fprintf(stderr, "read: %d\n", i);
			fprintf(stderr, "buffer: %s\n", buf);
			#endif
                }
      }

	close(sockfd);

	return 0;
}

linux网络编程之AF_INET AF_INET6 AF_UNSPEC

int getaddrinfo(const char *node, const char *service,
                const struct addrinfo *hints,
                struct addrinfo **res);
struct addrinfo {
    int ai_flags;
    int ai_family;
    int ai_socktype;
    int ai_protocol;
    socklen_t ai_addrlen;
    struct sockaddr *ai_addr;
    char *ai_canonname;
    struct addrinfo *ai_next;
};

ai_family参数指定调用者期待返回的套接口地址结构的类型。 它的值包括三种:

  1. AF_INET: 函数返回IPV4相关的地址信息
  2. AF_INET6: 函数返回IPV6相关的地址信息
  3. AF_UNSPEC: 函数返回的是适用于指定主机名和服务名且适合任何协议族的地址

如果某个主机既有AAAA记录(IPV6)地址,同时又有A记录(IPV4)地址,那么AAAA记录将作为sockaddr_in6结构返回,而A记录则作为sockaddr_in结构返回。

ref: http://blog.sina.com.cn/s/blog_8184e033010134c4.html

mplayer 常用命令

查看视频信息

mplayer -vo  null -vc null -nosound  -frames 0 -identify

使用vdpau解码器

mplayer -vo vdpau -vc ffh264vdpau [filename]

ffmpeg 常用命令

把mpg文件转换成一系列JPG图片

ffmpeg -i video.mpg image%d.jpg

其他支持的格式:

 PGM, PPM, PAM, PGMYUV, JPEG, GIF, PNG, TIFF, SGI ...

MP4转换MOV

这里只是转换了包装格式,不改变视频和音频编码格式。 -vcodec copy:拷贝源视频编码格式 -acodec copy:拷贝源音频编码格式

ffmpeg -i  inputfile.mp4  -vcodec  copy  -acodec  copy  output.mov

其它常用参数: -s:设置视频大小

ffmpeg -i  inputfile.mp4  -vcodec  copy  -acodec  copy -s  1920x1080  output.mov

-r:设置视频帧率

ffmpeg -i  inputfile.mp4  -vcodec  copy  -acodec  copy  -r  29.97  output.mov 

-b:设置视频码率

ffmpeg  -i  inputfile.mov  -acodec copy  -vcodec copy -s 1920x1080  -r 25  -b 20k  output.mov

捕捉音频

ffmpeg -f alsa -i hw:0 alsaout.wav

Json格式输出视频信息

ffprobe -v quiet -print_format json -show_format -show_streams 1kHz_0dBfs_L_aacPlusv2_32.aac

TS 切片命令

ffmpeg -i input_file -c copy -map 0  -f segment -segment_list  out.m3u8 -segment_time 10  file%04d.ts

关键帧信息显示

ffprobe -loglevel error -skip_frame nokey -select_streams v:0 -show_entries frame=pkt_pts_time -of csv=print_section=0 input.mp4
ffprobe -select_streams v -show_frames input.mp4

jsoncpp的简单使用

OS:ubuntu 12.04

JSONCPP : 0.5.0

关于JSONCPP

JSONCPP是一个比较流行的C/C++用来解析json的库,最新的版本是0.5.0,源代码下载地址点击 这里

JSONCPP的编译需要使用scons(ubuntu的用户直接apt-get install scons即可),编译成功后会在jsoncpp-src-0.5.0/libs/linux-gcc-4.7/ 下生成一个libjson_linux-gcc-4.7_libmt.so,开发头文件在include文件夹下。在编译自己的项目时需要加入-ljson_linux-gcc-4.7_libmt编译参数。

JSON结构

Value

alt none

String

alt none

Number

alt none

Object

json中的object是“名称/值”对的无序集合,类似于STL中的map。一个object以左大括号’{‘开始,右大括号结束’}’,名称和值之间使用冒号’:’分割,“名称/值”对与“名称/值”对之间使用逗号’,’分割。object可以被嵌套,可以作为其他类型的子元素。 一些例子:

  • {“id” : 1}

  • {“id” : 1, “name” : “lnmcc”, “age” : 100}

alt none

Array

json中的数组,以左方括号’[‘开始,右方括号’]’结束,元素跟元素之间以逗号’,’分割。 一个例子:

  • { “teacher” : [ {“name” : “lnmcc”}, {“name” : “word”} ] }

alt none

使用JSONCPP解析json文件

文件test.json内容:

{
    "id":7,
    "type":"pic",
    "deps":[
     {"order":1,"path":"/home/11.bmp"},
     {"order":1,"path":"/home/22.bmp"},
     {"order":1,"path":"/home/44.bmp"},
     {"order":2,"path":"/home/44.bmp"}
]
}
bool parseFile2(std::string path) {

	std::ifstream in;
	in.open(path.c_str(), std::ifstream::in);
	assert(in.is_open());

	Json::Reader reader;
	Json::Value value;

	if (!reader.parse(in, value, false)) {
		std::cerr  << "paser json file error!" << std::endl;
		return false;
	}

	std::cout << "id : "  << value["id"].asInt() << std::endl;
	std::cout << "type : " << value["type"].asString() << std::endl;
        
        Json::Value array;
        array = value["deps"];

	for(unsigned int i = 0; i < array.size(); i++) {
            std::cout << "order : " << array[i]["order"].asInt() << std::endl;
            std::cout << "path : " << array[i]["path"].asString() << std::endl;
        }	

	return true;
}

如果不是从文件读入, JSONCPP也可以直接处理json字符串:

bool parseString(std::string str) {

	Json::Reader reader;
	Json::Value value;

	if (!reader.parse(str, value)) {
		std::cerr << "paser json string error!" << std::endl;
		return false;
	}

        ...  ...

	return true;
}