/***
This file is part of systemd.
Copyright 2012 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <string.h>
#include "alloc-util.h"
#include "string-util.h"
#include "util.h"
#include "socket-util.h"
static void test_should_pass(const char *p) {
usec_t t, q;
char buf[FORMAT_TIMESTAMP_MAX], buf_relative[FORMAT_TIMESTAMP_RELATIVE_MAX], *sp;
assert_se(parse_timestamp(p, &t) >= 0);
format_timestamp_us(buf, sizeof(buf), t);
log_info("%s", buf);
/* Chop off timezone */
sp = strrchr(buf, ' ');
assert_se(sp);
*sp = 0;
assert_se(parse_timestamp(buf, &q) >= 0);
assert_se(q == t);
format_timestamp_relative(buf_relative, sizeof(buf_relative), t);
log_info("%s", strna(buf_relative));
assert_se(parse_timestamp(buf, &q) >= 0);
}
static void test_should_parse(const char *p) {
usec_t t;
assert_se(parse_timestamp(p, &t) >= 0);
}
static void test_should_fail(const char *p) {
usec_t t;
assert_se(parse_timestamp(p, &t) < 0);
}
static void test_one(const char *p) {
_cleanup_free_ char *with_utc;
log_info("Test: %s", p);
with_utc = strjoin(p, " UTC", NULL);
test_should_pass(p);
test_should_pass(with_utc);
}
static void test_one_noutc(const char *p) {
_cleanup_free_ char *with_utc;
log_info("Test: %s", p);
with_utc = strjoin(p, " UTC", NULL);
test_should_pass(p);
test_should_fail(with_utc);
}
int main1(int argc, char *argv[]);
int main1(int argc, char *argv[]) {
test_one("17:41");
test_one("18:42:44");
test_one("18:42:44.0");
test_one("18:42:44.999999999999");
test_one("12-10-02 12:13:14");
test_one("12-10-2 12:13:14");
test_one("12-10-03 12:13");
test_one("2012-12-30 18:42");
test_one("2012-10-02");
test_one("Tue 2012-10-02");
test_one_noutc("now");
test_one("yesterday");
test_one("today");
test_one("tomorrow");
test_one_noutc("+2d");
test_one_noutc("+2y 4d");
test_one_noutc("5months ago");
test_one_noutc("@1395716396");
test_should_parse("today UTC");
test_should_fail("today UTC UTC");
return 0;
}
#include <stdio.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <netdb.h>
#include <errno.h>
#define MAX_EVENT 20
#define READ_BUF_LEN 256
extern void hexdump_debug (unsigned long bse, char *buf, int len);
void hexdump_debug (unsigned long bse, char *buf, int len)
{
int pos;
char line[80];
while (len > 0)
{
int cnt, i;
pos = snprintf (line, sizeof (line), "%08lx ", bse);
cnt = 16;
if (cnt > len)
cnt = len;
for (i = 0; i < cnt; i++)
{
pos += snprintf (&line[pos], sizeof (line) - pos,
"%02x ", (unsigned char) buf[i]);
if ((i & 7) == 7)
line[pos++] = ' ';
}
for (; i < 16; i++)
{
pos += snprintf (&line[pos], sizeof (line) - pos, " ");
if ((i & 7) == 7)
line[pos++] = ' ';
}
line[pos++] = '|';
for (i = 0; i < cnt; i++)
line[pos++] = ((buf[i] >= 32) && (buf[i] < 127)) ? buf[i] : '.';
line[pos++] = '|';
line[pos] = 0;
printf ("%s\n", line);
/* Print only first and last line if more than 3 lines are identical. */
if (len >= 4 * 16
&& ! memcmp (buf, buf + 1 * 16, 16)
&& ! memcmp (buf, buf + 2 * 16, 16)
&& ! memcmp (buf, buf + 3 * 16, 16))
{
printf ("*\n");
do
{
bse += 16;
buf += 16;
len -= 16;
}
while (len >= 3 * 16 && ! memcmp (buf, buf + 2 * 16, 16));
}
bse += 16;
buf += 16;
len -= cnt;
}
}
/**
* 设置 file describe 为非阻塞模式
* @param fd 文件描述
* @return 返回0成功,返回-1失败
*/
static int make_socket_non_blocking (int fd) {
int flags, s;
// 获取当前flag
flags = fcntl(fd, F_GETFL, 0);
if (-1 == flags) {
perror("Get fd status");
return -1;
}
//printf( "flags = 0x%x\n", flags );
flags |= O_NONBLOCK;
//printf( "flags = 0x%x\n", flags );
// 设置flag
s = fcntl(fd, F_SETFL, flags);
if (-1 == s) {
perror("Set fd status");
return -1;
}
return 0;
}
int main(int argc, char *argv[])
{
//epoll 实例 file describe
int epfd = 0;
int listenfd = 0;
int result = 0;
struct epoll_event ev, event[MAX_EVENT];
// 绑定的地址
const char * const local_addr = "192.168.1.105";
struct sockaddr_in server_addr = { 0 };
union sockaddr_union snl;
socklen_t addrlen;
int r;
char *p;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
//listenfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
if (-1 == listenfd) {
perror("Open listen socket");
return -1;
}
/* Enable address reuse */
int on = 1;
// 打开 socket 端口复用, 防止测试的时候出现 Address already in use
result = setsockopt( listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) );
if (-1 == result) {
perror ("Set socket");
return 0;
}
server_addr.sin_family = AF_INET;
printf( "sizeof(server_addr.sin_addr) = %d\n", sizeof(server_addr.sin_addr) );
hexdump_debug(0, &server_addr.sin_addr, sizeof(server_addr.sin_addr));
inet_aton (local_addr, &(server_addr.sin_addr));
hexdump_debug(0, &server_addr.sin_addr, sizeof(server_addr.sin_addr));
server_addr.sin_port = htons(8080);
result = bind(listenfd, (const struct sockaddr *)&server_addr, sizeof (server_addr));
if (-1 == result) {
perror("Bind port");
return 0;
}
result = make_socket_non_blocking(listenfd);
if (-1 == result) {
return 0;
}
result = listen(listenfd, 200);
if (-1 == result) {
perror("Start listen");
return 0;
}
// 创建epoll实例
epfd = epoll_create1(0);
if (1 == epfd) {
perror("Create epoll instance");
return 0;
}
ev.data.fd = listenfd;
ev.events = EPOLLIN | EPOLLET /* 边缘触发选项。 */;
// 设置epoll的事件
result = epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev);
if(-1 == result) {
perror("Set epoll_ctl");
return 0;
}
for ( ; ; ) {
int wait_count;
// 等待事件
wait_count = epoll_wait(epfd, event, MAX_EVENT, -1);
printf( "wait_count = %d\n", wait_count );
for (int i = 0 ; i < wait_count; i++) {
uint32_t events = event[i].events;
// IP地址缓存
char host_buf[NI_MAXHOST];
// PORT缓存
char port_buf[NI_MAXSERV];
int __result;
// 判断epoll是否发生错误
printf( "event[i].data.fd = %d\n", event[i].data.fd );
if ( events & EPOLLERR || events & EPOLLHUP || (! events & EPOLLIN)) {
printf("Epoll has error\n");
close (event[i].data.fd);
continue;
} else if (listenfd == event[i].data.fd) {
// listen的 file describe 事件触发, accpet事件
for ( ; ; ) { // 由于采用了边缘触发模式,这里需要使用循环
struct sockaddr in_addr = { 0 };
socklen_t in_addr_len = sizeof (in_addr);
int accp_fd = accept(listenfd, &in_addr, &in_addr_len);
printf( "accp_fd = %d\n", accp_fd );
if (-1 == accp_fd) {
//perror("Accept123");
break;
}else{
//perror("Accept456");
}
/* get the address the kernel has assigned us
* it is usually, but not necessarily the pid
*/
//addrlen = sizeof(struct sockaddr_in);
//printf( "sizeof(snl) = %d\n", sizeof(snl) );
//printf( "accp_fd = %d\n", accp_fd );
//hexdump_debug(0, &snl.in, addrlen);
//printf( "addrlen = %d\n", addrlen );
//r = getsockname(accp_fd, &snl.in, &addrlen);
//printf( "addrlen = %d\n", addrlen );
//printf( "r = %d\n", r );
//hexdump_debug(0, &snl.in, addrlen);
//获取与文件句柄所绑定的套接字的ip地址
//即本机地址 或者是进程的pid(如果是系统内部通讯,应用与内核之间的通讯)
__result = getnameinfo(&in_addr, sizeof (in_addr),
host_buf, sizeof (host_buf) / sizeof (host_buf[0]),
port_buf, sizeof (port_buf) / sizeof (port_buf[0]),
NI_NUMERICHOST | NI_NUMERICSERV);
//显示来连接此服务器的客户端的ip地址与端口号
//通过accept得到客户端的ip地址与端口号
if (! __result) {
printf("New connection: host = %s, port = %s\n", host_buf, port_buf);
}
__result = make_socket_non_blocking(accp_fd);
if (-1 == __result) {
return 0;
}
ev.data.fd = accp_fd;
ev.events = EPOLLIN | EPOLLET;
// 为新accept的 file describe 设置epoll事件
__result = epoll_ctl(epfd, EPOLL_CTL_ADD, accp_fd, &ev);
if (-1 == __result) {
perror("epoll_ctl");
return 0;
}
}
continue;
} else {
// 其余事件为 file describe 可以读取
int done = 0;
// 因为采用边缘触发,所以这里需要使用循环。如果不使用循环,程序并不能完全读取到缓存区里面的数据。
for ( ; ;) {
ssize_t result_len = 0;
char buf[READ_BUF_LEN] = { 0 };
result_len = read(event[i].data.fd, buf, sizeof (buf) / sizeof (buf[0]));
if (-1 == result_len) {
if (EAGAIN != errno) {
perror ("Read data");
done = 1;
}
break;
} else if (! result_len) {
done = 1;
break;
}
write(STDOUT_FILENO, buf, result_len);
}
if (done) {
printf("Closed connection\n");
close (event[i].data.fd);
}
}
}
}
close (epfd);
return 0;
}
本文探讨了系统时间的解析方法,包括多种时间格式的识别与转换,并深入介绍了非阻塞网络编程的实现细节,如socket设置、epoll事件处理及边缘触发模式的应用。
3982

被折叠的 条评论
为什么被折叠?



