May
14
epoll相关代码出自“man epoll”。发现在网上找相关代码还有点麻烦。
p.s. 推荐 apt-get source libevent 找找里面的 epoll.c 文件里的相关实现。
这里有另一个很详细的说明: https://banu.com/blog/2/how-to-use-epoll-a-complete-example-in-c/
p.s. 推荐 apt-get source libevent 找找里面的 epoll.c 文件里的相关实现。
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <sys/wait.h>
#define SERVPORT 9527 /*服务器监听端口号 */
#define BACKLOG 10 /* 最大同时连接请求数 */
void setnonblocking(int sock)
{
int opts;
opts = fcntl(sock,F_GETFL);
if(opts<0)
{
perror("fcntl(sock,GETFL)");
exit(1);
}
opts = opts|O_NONBLOCK;
if(fcntl(sock,F_SETFL,opts)<0)
{
perror("fcntl(sock,SETFL,opts)");
exit(1);
}
}
void do_use_fd(int client_fd)
{
const char str[] = "God bless you!\n";
if (send(client_fd, str, sizeof(str), 0) == -1)
perror("send");
close(client_fd);
}
int main()
{
int sockfd;
struct sockaddr_in my_addr;
struct sockaddr_in remote_addr;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(SERVPORT);
my_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(my_addr.sin_zero), 8);
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
perror("bind");
exit(1);
}
printf("bind ok\n");
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
printf("listen ok\b");
size_t sin_size = sizeof(struct sockaddr_in);
#define MAX_EVENTS 10
struct epoll_event ev, events[MAX_EVENTS];
int conn_sock, nfds, epollfd;
epollfd = epoll_create(10);
if (epollfd == -1) {
perror("epoll_create");
exit(EXIT_FAILURE);
}
printf("epoll_create\n");
ev.events = EPOLLIN;
ev.data.fd = sockfd;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &ev) == -1) {
perror("epoll_ctl: sockfd");
exit(EXIT_FAILURE);
}
printf("epoll_ctl ok\n");
for (;;) {
printf("start epoll_wait\n");
nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
if (nfds == -1) {
perror("epoll_pwait");
exit(EXIT_FAILURE);
}
printf("epoll_wait returns, nfds = %d\n", nfds);
for (int n = 0; n < nfds; ++n) {
if (events[n].data.fd == sockfd) {
conn_sock = accept(sockfd,
(struct sockaddr *) &remote_addr, &sin_size);
if (conn_sock == -1) {
perror("accept");
exit(EXIT_FAILURE);
}
setnonblocking(conn_sock);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = conn_sock;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock,
&ev) == -1) {
perror("epoll_ctl: conn_sock");
exit(EXIT_FAILURE);
}
} else {
do_use_fd(events[n].data.fd);
}
}
}
}
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <sys/wait.h>
#define SERVPORT 9527 /*服务器监听端口号 */
#define BACKLOG 10 /* 最大同时连接请求数 */
void setnonblocking(int sock)
{
int opts;
opts = fcntl(sock,F_GETFL);
if(opts<0)
{
perror("fcntl(sock,GETFL)");
exit(1);
}
opts = opts|O_NONBLOCK;
if(fcntl(sock,F_SETFL,opts)<0)
{
perror("fcntl(sock,SETFL,opts)");
exit(1);
}
}
void do_use_fd(int client_fd)
{
const char str[] = "God bless you!\n";
if (send(client_fd, str, sizeof(str), 0) == -1)
perror("send");
close(client_fd);
}
int main()
{
int sockfd;
struct sockaddr_in my_addr;
struct sockaddr_in remote_addr;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(SERVPORT);
my_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(my_addr.sin_zero), 8);
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
perror("bind");
exit(1);
}
printf("bind ok\n");
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
printf("listen ok\b");
size_t sin_size = sizeof(struct sockaddr_in);
#define MAX_EVENTS 10
struct epoll_event ev, events[MAX_EVENTS];
int conn_sock, nfds, epollfd;
epollfd = epoll_create(10);
if (epollfd == -1) {
perror("epoll_create");
exit(EXIT_FAILURE);
}
printf("epoll_create\n");
ev.events = EPOLLIN;
ev.data.fd = sockfd;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &ev) == -1) {
perror("epoll_ctl: sockfd");
exit(EXIT_FAILURE);
}
printf("epoll_ctl ok\n");
for (;;) {
printf("start epoll_wait\n");
nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
if (nfds == -1) {
perror("epoll_pwait");
exit(EXIT_FAILURE);
}
printf("epoll_wait returns, nfds = %d\n", nfds);
for (int n = 0; n < nfds; ++n) {
if (events[n].data.fd == sockfd) {
conn_sock = accept(sockfd,
(struct sockaddr *) &remote_addr, &sin_size);
if (conn_sock == -1) {
perror("accept");
exit(EXIT_FAILURE);
}
setnonblocking(conn_sock);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = conn_sock;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock,
&ev) == -1) {
perror("epoll_ctl: conn_sock");
exit(EXIT_FAILURE);
}
} else {
do_use_fd(events[n].data.fd);
}
}
}
}
这里有另一个很详细的说明: https://banu.com/blog/2/how-to-use-epoll-a-complete-example-in-c/
Feb
9
这几天简单学习了一下jsp的使用(主要是看《jsp开发web应用系统参考书籍》系列pdf),大致做一下记录。
首先是环境,jdk是必须的,服务器我用tomcat,因为以前搞noah/oak的时候整过,熟悉些。具体的配置不赘述了,网上很多,无非是JAVA_HOME CLASSPATH CATALINA_HOME之类的环境变量。此外为了连上mysql,还要去下个jar,比如mysql-connector-java-5.0.8-bin.jar,可以在网上搜到。这个要放在tomcat/shared/lib/下面。当然,也是可以放在jsp的WEB-INF/lib下面,但是这个我没研究过,不太了解细节。
最简单地写JSP,其实和写ASP/PHP很像,把java当成一个面向过程的语言填上去就行了。比如经典的hello world:
因为这里的java和普通的*.java程序不一样,所有有些语句也得变,比如import不能直接用了,必须这么写:
格式为 <%@ page oo="xx" %> 这样的oo和xx有很多个,比如session开关就是通过这种方式控制,详情参考那些pdf。包含文件则用<%@ include file="xxxx" %>这样的格式。
在编写的过程中要获取GET/POST等请求的数据以及客户端IP等信息的时候,可以使用默认import进来的request对象,有getParameter()、getMethod()、getRequestURI()、getRemoteADDR()....等方法。相当于php的$_GET/$_POST/$_SERVER等变量的大杂烩。
要控制输出,比如HTTP Header或者具体的Cookie字段,则使用response对象的addCookie()、addHeader()等方法。
Session,则是使用session对象。但是要先<%@ page session="true" %>开启session。
此外还有一个和ASP同样性质也同名的Application对象。看起来像是抄ASP的。就是一个和服务器同生死的全局变量。
以上就是最简单的jsp开发需要的一些东西了。至少开发一个留言板什么都OK了 :)
至于Java Beans,这个是第六章,我还没看...
首先是环境,jdk是必须的,服务器我用tomcat,因为以前搞noah/oak的时候整过,熟悉些。具体的配置不赘述了,网上很多,无非是JAVA_HOME CLASSPATH CATALINA_HOME之类的环境变量。此外为了连上mysql,还要去下个jar,比如mysql-connector-java-5.0.8-bin.jar,可以在网上搜到。这个要放在tomcat/shared/lib/下面。当然,也是可以放在jsp的WEB-INF/lib下面,但是这个我没研究过,不太了解细节。
最简单地写JSP,其实和写ASP/PHP很像,把java当成一个面向过程的语言填上去就行了。比如经典的hello world:
<html>
<body>
<%
out.println("Hello, world!\n"); //在jsp里输出就用out啦,不是System.out。
%>
</body>
</html>
<body>
<%
out.println("Hello, world!\n"); //在jsp里输出就用out啦,不是System.out。
%>
</body>
</html>
因为这里的java和普通的*.java程序不一样,所有有些语句也得变,比如import不能直接用了,必须这么写:
引用
<%@ page import="java.sql.*" %>
格式为 <%@ page oo="xx" %> 这样的oo和xx有很多个,比如session开关就是通过这种方式控制,详情参考那些pdf。包含文件则用<%@ include file="xxxx" %>这样的格式。
在编写的过程中要获取GET/POST等请求的数据以及客户端IP等信息的时候,可以使用默认import进来的request对象,有getParameter()、getMethod()、getRequestURI()、getRemoteADDR()....等方法。相当于php的$_GET/$_POST/$_SERVER等变量的大杂烩。
要控制输出,比如HTTP Header或者具体的Cookie字段,则使用response对象的addCookie()、addHeader()等方法。
Session,则是使用session对象。但是要先<%@ page session="true" %>开启session。
此外还有一个和ASP同样性质也同名的Application对象。看起来像是抄ASP的。就是一个和服务器同生死的全局变量。
以上就是最简单的jsp开发需要的一些东西了。至少开发一个留言板什么都OK了 :)
至于Java Beans,这个是第六章,我还没看...
Jan
30
$from = 'FROM: "=?UTF-8?B?' . base64_encode($yourname) . '?=" <from@yourdomain.com>';
$content = 'Content-Type: text/html; charset=UTF-8';
if (mail("to@yourdomain.com", "Subject", $msg, "{$from}\r\n{$content}\r\n")) {
echo "搞定!";
}
else {
echo "可耻地失败鸟...";
}
$content = 'Content-Type: text/html; charset=UTF-8';
if (mail("to@yourdomain.com", "Subject", $msg, "{$from}\r\n{$content}\r\n")) {
echo "搞定!";
}
else {
echo "可耻地失败鸟...";
}
大致记录一下:
额外的HEADER指定了FROM和Content-Type字段
Content-Type用于标识内容是什么格式(text/html),什么编码(UTF-8)
下面这一行表示发件人,显示名称“xxxxxx”是经过BASE64编码(那个?B?的意思)后的UTF-8字符。
FROM: "=?UTF-8?B?xxxxxxxx?=" <from@yourdomain.com>
如果Subject需要中文字符,应该类似地:
SUBJECT: =?UTF-8?B?xxxxxxx?=
Jan
23
php代码
侧边栏的内容:
<?php
define ("MAX_MSG_COUNT", 5);
define ("USER_NAME", 'felix021');
$msg_c = isset($_GET['c']) ? intval($_GET['c']) : MAX_MSG_COUNT;
$user = isset($_GET['u']) ? $_GET['u'] : USER_NAME;
require ('../lib/twitter.php'); //注: 此文件从twitese的lib目录下提取,并增加了
//define("API_URL", "http://twitter.com");
$t = new twitter();
$s = $t->userTimeline(1, $user);
$msg = array();
for ($i = 0; $i < $msg_c; $i++) {
$msg[$i] = htmlspecialchars(stripslashes($s[$i]->text));
$msg[$i] = preg_replace(
array(
"/(\w+):\/\/([a-zA-Z0-9\.\/\-%+\?#_=@:&;])*/i",
'/(\s|^)@([a-zA-Z0-9_-]+)/',
'/(\s|^)#([a-zA-Z0-9_-]+)/',
),
array(
'<a href="\0" target="_blank">\0</a>',
'\1<a href="/t/\2" target="_blank">@\2</a>',
'\1<a href="/t/~\2" target="_blank">#\2</a>',
),
$msg[$i]
);
}
echo json_encode($msg);
?>
define ("MAX_MSG_COUNT", 5);
define ("USER_NAME", 'felix021');
$msg_c = isset($_GET['c']) ? intval($_GET['c']) : MAX_MSG_COUNT;
$user = isset($_GET['u']) ? $_GET['u'] : USER_NAME;
require ('../lib/twitter.php'); //注: 此文件从twitese的lib目录下提取,并增加了
//define("API_URL", "http://twitter.com");
$t = new twitter();
$s = $t->userTimeline(1, $user);
$msg = array();
for ($i = 0; $i < $msg_c; $i++) {
$msg[$i] = htmlspecialchars(stripslashes($s[$i]->text));
$msg[$i] = preg_replace(
array(
"/(\w+):\/\/([a-zA-Z0-9\.\/\-%+\?#_=@:&;])*/i",
'/(\s|^)@([a-zA-Z0-9_-]+)/',
'/(\s|^)#([a-zA-Z0-9_-]+)/',
),
array(
'<a href="\0" target="_blank">\0</a>',
'\1<a href="/t/\2" target="_blank">@\2</a>',
'\1<a href="/t/~\2" target="_blank">#\2</a>',
),
$msg[$i]
);
}
echo json_encode($msg);
?>
侧边栏的内容:
<div id="twitter" style="font-size:12px"></div>
<script>
function getXML() {
var a = null;
try {
if (window.XMLHttpRequest) {
a = new XMLHttpRequest();
} else if (window.ActiveXObject) {
a = new ActiveXObject("Msxml2.XMLHTTP");
}
}catch(e) {}
return a;
}
function _t(c) {
var x = getXML();
x.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
var g = eval(this.responseText);
var tt = '';
var t = document.getElementById('twitter');
for(var i = 0; i < g.length; i++){
tt += g[i] + (i+1 == g.length ? "" : "<hr/>");
}
t.innerHTML = tt;
}
}
x.open("GET", "/blog/tt.php?c="+c, true);
x.send('');
}
_t(4);
</script>
<script>
function getXML() {
var a = null;
try {
if (window.XMLHttpRequest) {
a = new XMLHttpRequest();
} else if (window.ActiveXObject) {
a = new ActiveXObject("Msxml2.XMLHTTP");
}
}catch(e) {}
return a;
}
function _t(c) {
var x = getXML();
x.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
var g = eval(this.responseText);
var tt = '';
var t = document.getElementById('twitter');
for(var i = 0; i < g.length; i++){
tt += g[i] + (i+1 == g.length ? "" : "<hr/>");
}
t.innerHTML = tt;
}
}
x.open("GET", "/blog/tt.php?c="+c, true);
x.send('');
}
_t(4);
</script>
Jan
22
RewriteEngine On
RewriteBase /t
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^~@].*)$ user.php?id=$1 [QSA,L]
RewriteRule ^(@.*)$ search.php?q=$1 [QSA,L]
RewriteRule ^~(.*)$ search.php?q=$1 [QSA,L]
RewriteBase /t
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^~@].*)$ user.php?id=$1 [QSA,L]
RewriteRule ^(@.*)$ search.php?q=$1 [QSA,L]
RewriteRule ^~(.*)$ search.php?q=$1 [QSA,L]
Jan
20
世界上最贵的网站出现在中国,而不是欧美等国家,充分体现了中国特色社会主义的优越性。
传送门:http://www.mof.gov.cn/mof/xinxi/zhongyangbiaoxun/zhongbiaogonggao/200912/t20091215_246271.html
为防止一小撮别有用心的人消灭社会主义的建设成果,特此存截图留念。

p.s. 还有一个670w造价的网站,传送门:
http://www.mof.gov.cn/mof/xinxi/zhongyangbiaoxun/zhongbiaogonggao/200912/t20091230_254406.html
相比之下一个150w造价的3间厕所,实在上不了台面啊!
@ 20100121 p.s.
rtmeme: RT @yuanxinting RT @xiaomi2020: 国家汉办3520万元建立网络孔子学院。中标公司是五洲汉风网络科技(北京)有限公司。该公司法人代表是胡志平。其另一职务是国家汉办副主任。也就是国家汉办开出了标书,是国家汉办创建了企业
@ 20100122 p.s.
此新闻已经开始被和谐,详见:Google搜索 中国工会网扩建项目 网易
传送门:http://www.mof.gov.cn/mof/xinxi/zhongyangbiaoxun/zhongbiaogonggao/200912/t20091215_246271.html
为防止一小撮别有用心的人消灭社会主义的建设成果,特此存截图留念。
p.s. 还有一个670w造价的网站,传送门:
http://www.mof.gov.cn/mof/xinxi/zhongyangbiaoxun/zhongbiaogonggao/200912/t20091230_254406.html
相比之下一个150w造价的3间厕所,实在上不了台面啊!
@ 20100121 p.s.
rtmeme: RT @yuanxinting RT @xiaomi2020: 国家汉办3520万元建立网络孔子学院。中标公司是五洲汉风网络科技(北京)有限公司。该公司法人代表是胡志平。其另一职务是国家汉办副主任。也就是国家汉办开出了标书,是国家汉办创建了企业
@ 20100122 p.s.
此新闻已经开始被和谐,详见:Google搜索 中国工会网扩建项目 网易
Jan
20
折腾了好久才弄出来,sigh,不熟这东西
引用
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} /(index\.php)?
RewriteRule ^.*$ - [L]
RewriteCond %{HTTP_HOST} 19880711\.com
RewriteRule ^(.*)$ http://www.felix021.com/$1 [QSA,L]
RewriteCond %{REQUEST_FILENAME} /(index\.php)?
RewriteRule ^.*$ - [L]
RewriteCond %{HTTP_HOST} 19880711\.com
RewriteRule ^(.*)$ http://www.felix021.com/$1 [QSA,L]
Jan
7
编译apache的时候默认应该是有mod_cgi的,如果不确定,可以加上--enable_cgi。
在httpd.conf里面增加(或修改,因为可能已经有这个东西了):如果你修改了“某路径”,那么后面对应的Directory一节也应该对应修改
下面是一个简单的C编写的cgi程序,gcc -o printall simple_cgi.c,把printall放在cgi-bin目录下面。然后访问:http://localhost/cgi-bin/printall,可以看到输出。特别注意一下,cgi不仅要打HTTP实体,还要打HTTP头信息。如果你实在懒得写,在实体前面加上一个回车就行了:) 否则你会看到apache的error_log里输出诸如"malformed header from script. Bad header="这样的错误信息。
特别点出一下,GET请求的query_string是在environ["QUERY_STRING"]里面,而POST请求的输入,是从stdin中读取。
在httpd.conf里面增加(或修改,因为可能已经有这个东西了):
引用
ScriptAlias /cgi-bin/ /某路径/cgi-bin/
引用
<Directory "/某路径/cgi-bin">
AllowOverride None
Options FollowSymLinks #如果不放心,这里还可以加上一个ExecCgi选项。
Order allow,deny
Allow from all
</Directory>
AllowOverride None
Options FollowSymLinks #如果不放心,这里还可以加上一个ExecCgi选项。
Order allow,deny
Allow from all
</Directory>
下面是一个简单的C编写的cgi程序,gcc -o printall simple_cgi.c,把printall放在cgi-bin目录下面。然后访问:http://localhost/cgi-bin/printall,可以看到输出。特别注意一下,cgi不仅要打HTTP实体,还要打HTTP头信息。如果你实在懒得写,在实体前面加上一个回车就行了:) 否则你会看到apache的error_log里输出诸如"malformed header from script. Bad header="这样的错误信息。
#include <stdio.h>
#include <stdlib.h>
extern char ** environ;
int main ()
{
int i;
puts("Content-Type: text/plain\n\n");
for (i = 0; environ[i] != NULL; i++) {
printf ("%s\n", environ[i]);
}
if (strncmp("POST", getenv("REQUEST_METHOD"), 4) == 0) {
char buf[1025];
while (1) {
fgets(buf, 1024, stdin);
printf( "%s", buf);
if (feof(stdin)) {
break;
}
}
}
return 0;
}
#include <stdlib.h>
extern char ** environ;
int main ()
{
int i;
puts("Content-Type: text/plain\n\n");
for (i = 0; environ[i] != NULL; i++) {
printf ("%s\n", environ[i]);
}
if (strncmp("POST", getenv("REQUEST_METHOD"), 4) == 0) {
char buf[1025];
while (1) {
fgets(buf, 1024, stdin);
printf( "%s", buf);
if (feof(stdin)) {
break;
}
}
}
return 0;
}
特别点出一下,GET请求的query_string是在environ["QUERY_STRING"]里面,而POST请求的输入,是从stdin中读取。