网络的一些相关知识:
网卡功能: 载波侦听, 冲突检测, 随机延时等待;
网线一般不得超过100米;
交换机的功能: 动态建立连接桥梁, 探知端口上有几台电脑, 自学习;
远距离传送: 铜线 + 中继器/光纤/微波 等 挑战在于:如何传更远, 更快, 减少错误;
局域网物理层的功能目标: 更准, 更快, 如何避免冲突;
链路, 就是连接相邻两台电脑的线路; 如何可靠的传输, 通过校验, 不是绝对安全, 但已经足够;
protocol是用来定义数据桢格式, 交互顺序的. 比如以太网802.1, 广域网ppp
? 流控制, 应答, "滑动窗口协议"
点到点保证可靠传送, 端到端可靠吗? 由于当中如果缺少整桢数据, 端到端并不可靠.
路由协议是用于路由器之间维护路由表的协议:
每个路由的下一跳要明确; 定期广播; 启动时广播;
以太网是当前应用最普遍的局域网技术;
mac地址在局域网内不重复, 但在不同的局域网可能重复;
socket = Sip + Sport +Tip +Tport 唯一确定一条网络通路;
HTTP请求格式:
telnet 80
GET / HTTP/1.1 \n
HOST: \n\n
如何软件手段获取域名的IP地址? 如何提取网页的特定信息?
linux中看路由: traceroute + webname
xp中看路由: tracert + webname
TCP/IP协议族层次,由上往下: 应用层->传输层->网络层->链路层
OSI参考模型7层, 由上往下: 应用层, 表示层, 会话层->传输层->网络层->数据链路层, 物理层
应用层协议:
FTP file transfer protocol, 允许用户以文件操作的方式与另一主机通信;
SMTP simple mail transfer protocol, 为系统间传送电子邮件;
TELNET telnet terminal protocol, 允许用户以虚终端方式访问远程主机;
HTTP hypertext transfer protocol, 环球www的基础;
TFTP trivial file transfer protocol, ftp的简化版本, 基于UDP协议;
传输层协议:
TCP transmission control protocol, 一种提供给用户进程的可靠的全双工的字节流面向连接的协议.
UDP user datagram protocol, 一种提供给用户进程的无连接的协议, 不执行正确性检查.
网络层协议:
IP internet protocol, 负责主机间数据路由和网络上数据的存储, 同时为ICMP, TCP, UDP提供分组发送服务;
ARP address resolution protocol, 此协议将网络地址映射到硬件地址;
RARP reverse address resolution protocol, 此协议将硬件地址映射到网络地址;
ICMP internet control message protocol, 此协议处理信关和主机间的差错和传送控制; 本身也是IP的一部分;
IP地址, 32bit, 4字节, 通常采用点分十进制记法: 192.168.0.1 ; Dotted decimal string representation;
特殊的IP地址: 255.255.255.255 网络内广播,路由器不转发;
子网掩码, 表明了该IP所在网络的地址范围;
路由表, 路由, 路由节点, 接口, 条目, 缺省路由条目;
路由: 数据报从源地址到目的地址所经过的道路, 由一系列路由节点的地址构成.
小端存储, 0x01020304, 后面的是小地址;
大端存储, 0x01020304, 前面的是小地址; 网络数据就是大端格式;
i386是小端存储, 一些大端存储的CPU有POWER PC, SUNSPARC.
转换函数:
uint16_t htons(uint16_t value); //s代表short
uint32_t htonl(uint32_t value); //l代表long
返回网络顺序的值;
uint16_t ntohs(uint16_t value);
uint32_t ntohs(uint32_t value);
返回主机顺序的值;
其他常用函数:
void bzero(void *dest, size_t nbytes);
void bcopy(const void *src, void *dest, size_t nbytes);
void bcmp(const void *ptr1, const void *ptr2, size_t nbytes);
void *memset(void *dest, int c, size_t len);
void *memcpy(void *dest, const void *src, size_t nbytes);
int memcmp(const void *ptr1, const void *ptr2, size_t nbytes);
地址转换:
点分十进制字符串 --inet_aton -->网络顺序32位整形值
162.105.129.7 <--inet_ntoa --0x 07 81 69 A2 (这是i386主机上打印出的值)
int inet_aton( const char *strptr, struct in_addr *addrptr); 地址有效返回非0, 无效返回0;
char *inet_ntoa( struct in_addr inaddr); 返回数据存在static memory中.
struct in_addr{
in_addr_t s_addr;
}
typedef u_int32_t in_addr_t;
inet_pton 和 inet_ntop较新, 可以处理ipv4, ipv6两种地址; p->presentation n->numeric
#include
int inet_pton( int family, const char *strptr, void *addrptr); 有效地址返回1, 无效返回0, 出错返回-1;
const char *inet_ntop( int family, const void *addrptr, char *strptr, size_t len);
成功返回结果指针, 出错返回NULL;
family 可以是AF_INET, AF_INET6
len 的定义如下:
#include
#define INET_ADDRSTRLEN 16 /*for ipv4 dotted-decimal */
#define INET6_ADDRSTRLEN 46 /*for ipv6 hex string */
socket是编程接口, 是一系列函数调用; 一对socket构成了交流数据的一个通道; 一个进程可以有多个socket;
#include
#include
int socket (int domain, int type, int protocol); //成功返回一个非负的描述符, 出错返回-1;
domain description
AF_INET Ipv4 protocols
AF_INET6 Ipv6 protocols
AF_UNIX Unix domain protocols
AF_UNSPEC Unspecified
type description
SOCK_STREAM stream socket
SOCK_DGRAM datagram socket
SOCK_RAW raw socket
protocol: 0
#include
#include
int bind( int sockfd, struct sockaddr *my_addr, socklen_t addlen); //成功返回0, 出错返回-1;
struct sockaddr{
sa_family_t sa_family;
char sa_data[14];
}
struct sockaddr_in{
sa_family_t sin_family;
in_port_t sin_port; //2bytes
struct in_addr sin_addr; //4bytes
char sin_zero[8];
}
这两个结构体指针可以互相强制转换;
地址值可以是INADDR_ANY通配地址, 也可以是本地ip地址.
本地可以有多个IP地址, 一旦绑定, 此socket上发送的数据以此地址为IP源地址;
端口可以分配一个非0, 也可以是0, 此时系统会分配一个非0值;
客户端通常不指定本地IP, 系统根据目的地址选择要使用的网卡, 然后用该网卡的地址作为源地址;
服务器, 一般设为INADDR_ANY, 由系统挑选一地址, 该地址是客户端连接请求是确定的;
客户端通常不需要bind, 服务器需要bind以表明使用的端口;
#include
int listen( int sockfd, int backlog); //成功返回0, 出错返回-1;
该函数使socket在协议地址上监听, 并为该socket建立一个连接队列, 保存到达的服务请求, 直到程序处理;
backlog 指定在请求队列中允许的最大请求数, 进入的连接请求将在队列中等待被accept. 多数系统缺省20;
如果队列已满, 新来的请求将被拒绝, 客户收到一个出错信息;
#include
#include
int accept( int sockfd, struct sockaddr *addr, socklen_t *addrlen); //成功返回非负的连接描述符, 出错-1;
用listen建立好输入队列后, 服务器可以调用accept阻塞式的等待客户的连接请求;
连接成功后往返回的连接描述符来读写数据; sockfd继续用于监听连接请求;
addr 用来存放客户端主机的信息;
#include
#include
int connect( int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen); //成功返回0, 出错-1;
用于客户端向服务器发出连接请求, 成功后可以用sockfd来读写数据;
serv_addr 是包含远端主机IP地址和端口号的指针;
出错返回-1, 并设置errno, 常见如下:
ETIMEOUT 连接超时;
ECONNREFUSED 服务器不在listen;
ENETUNREACH 网络不通
常用于TCP客户端, 服务器一般不主动去连;
在UDP应用中, 也可以用connect, 目的是建立双方的ip-port对, 可直接使用read, write, 无需在sendto中指定;
#include
int read( socketfd, void *buf, size_t n); //成功返回读取的字节数, 出错返回-1;
int write(socketfd, void *buf, size_t n); //成功返回写入的字节数, 出错返回-1;
对于read, 如果读出的数目小于n, 可能是接近文件结尾, 从终端读, 被信号中断等原因;
如果还没开始读, 就被信号打断, 此时返回-1, 并置errno为EINTR.
对于write, 如果还没开始写, 就被信号打断, 此时返回-1, 并置errno为EINTR.
#include
#include int recv(int sockfd, void *buf, int len, int flags);
int send(int sockfd, void *buf, int len, int flags);
这2个函数比read, write多了个flags控制参数:
flags |
description |
recv |
send |
MSG_DONTROUTE |
bypass routing table lookup
|
|
* |
MSG_DONTWAIT |
only this operation is nonblocking
|
* |
* |
MSG_OOB |
send or receive out-of-band data
|
* |
* |
MSG_PEEK |
peek at incoming message
|
* |
|
MSG_WAITALL |
wait for all the data |
* |
|
#include
int close( int fd); //成功返回0, 出错返回-1;
用于TCP时, 如果发送队列非空, 发送之, 然后终止TCP连接;
#include
#include
int recvfrom( int sockfd, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);
int sendto( int sockfd, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);
这两个函数比recv, send这两个函数多了后2个地址参数;包含了IP地址和端口信息; 都可以用在TCP, UDP情况;
from是等待被填写的消息的源地址及端口, to是填好的目的地址及端口;
可设置socket为非阻塞型:
#include
#include
int fcntl( int fd, int cmd);
int save_flags;
save_flags = fcntl(socket_fd, F_GETFL); //获得当前状态
save_flags | = O_NONBLOCK;
fcntl( socket_fd, F_SETFL, save_flags); //设置指定的新状态
设置为非阻塞后:
对于read, recv, recvfrom 如果没有可用的信息, 返回-1, errno设为EAGAIN;
对于write, send, sendto 如果消息无法放入buffer, 返回-1, errno设为EAGAIN;
对于accept 如果不行, 返回-1, errno设为EAGAIN;
对于connect, 如果不行, 返回-1, errno设为EINPROGRESS;
select及其相关函数:
//according to POSIX 1003.1-2001.
#include
//according to earlier standards.
#include
#include
#include
int select(int maxfdpl, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
成功返回所有sets中描述符的个数, 超时返回0, 出错返回-1;
检查readfds中带1的位, 若有数据可读, 1保留, 否则清零;
检查writefds中带1的位, 若写不被阻塞, 表示可写, 1保留, 否则清零;
最后返回剩下的累计readfds, writefds, exceptfds当中1的总数;
四个宏用于fd_set操作:
FD_CLR(int fd, fd_set *set); //用来对set删除fd;
FD_ISSET(int fd, fd_set *set); //指示fd是不是已经是set的一部分;
FD_SET(int fd, fd_set *set); //对set添加fd;
FD_ZERO(fd_set *set); //清空set;
timeout是从调用开始到select返回前, 会经历的最大等待时间;
如果为0, 会立即返回; 如果为NULL, 会阻塞式等待;
在linux中, select函数会改变timeout值, 指示还剩下的时间, 所以, 最好在循环里要重新给timeout赋值;
struct timeval{
long tv_sec; //seconds
long tv_usec; //microseconds
}
#include
signal(SIGPIPE, SIG_IGN) 忽略SIGPIPE信号, 此处没用sigaction函数;
如果服务端已经关闭, client继续给这个连接发送内容, 第一次写, 根据TCP协议, 会收到RST响应, 如果还要写, 系统会发送个SIGPIPE信号给进程, 该信号的默认反应是关闭进程; 在此忽略.
如果用^C把server终止掉, 由于client端没有执行close来关闭连接, 连接还会等待client的FIN包一段时间, 如果用netstat -a查看, 发现有FIN_WAIT2状态存在, 这说明目前有socket在此地址上使用, 再次bind失败.
解决办法是: 使用setsockopt, 使这个socket可以被重用地址, 在soket调用和bind之间加上这一段:
int opt=1;
setsockopt( listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
#define offset( TYPE, MEMBER ) ( ( int ) &( ( TYPE * ) 0 ) ->MEMBER)
该宏用来获取结构体成员的偏移量;
服务端bind不是必须的, 它是要告诉操作系统, 某个socket使用某个地址和端口, 如果不指定, 系统会分配一个.
UDP客户端也能使用connect, 然后也可以使用无地址信息的读写函数了, 如:read, write, send, recv等.
服务端的程序可以有几种方案: 多进程, 多线程, select,
总而言之:
对于server, 步骤如下:
配置本地要监听的sin地址->socket得到listen_fd->
把listen_fd监听描述符bind到sin上->设置listen开始监听->
acept阻塞等待, 得到conn_fd用于读写, 得到pin的被填充的内容保存客户端信息->
对conn_fd进行read, write操作->与某客户端连接结束后close(conn_fd)->
整个服务程序结束时close(listen_fd);
对于client, 步骤如下:
配置目标地址pin->socket得到sock_fd->
用sock_fd去connect目标地址pin, 若成功返回则可开始用sock_fd进行read, write操作->
结束后close(sock_fd);
一些关于socket的例程:
//判断大小端的方法:
uion{
int s;
char c[4];
}un;
un.s = 0x01020304
if (un.c[0] == 1)
printf("big-endian\n");
if (un.c[0] == 4)
printf("little-endian\n");
else
printf("unknow\n");
/*client.c
*a simple client program
*/
#include
#include
#include
#include
#include
#include
#include
#define MAXLINE 80
int port = 8000;
int main(int argc, char *argv[])
{
struct sockaddr_in pin;
char buf[MAXLINE];
int sock_fd;
char *str = "A default test string";
if (argc > 1)
str = argv[1];
bzero(&pin, sizeof(pin));
pin.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", &pin.sin_addr);
pin.sin_port = htons(port);
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
connect(sock_fd, (void*)&pin, sizeof(pin));
write(sock_fd, str, strlen(str) + 1);
read(sock_fd, buf, MAXLINE);
printf("Response from server:%s\n", buf);
close(sock_fd);
return 0;
}
/*server.c
*a simple server program
*/
#include
#include
#include
#include
#include
#include
#include
#define MAXLINE 80
int port = 8000;
int main(void)
{
struct sockaddr_in sin;
struct sockaddr_in pin;
int listen_fd;
int conn_fd;
int address_size = sizeof(pin);
char buf[MAXLINE];
char str[INET_ADDRSTRLEN];
int i;
int len;
bzero(&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(port);
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
bind(listen_fd, (struct sockaddr *)&sin, sizeof(sin));
listen(listen_fd, 20);
printf("Accepting connections ...\n");
while(1)
{
conn_fd = accept(listen_fd,
(struct sockaddr *)&pin, &address_size);
read(conn_fd, buf, MAXLINE);
printf("received from client %s at port %d: %s\n",
inet_ntop(AF_INET, &pin.sin_addr, str,
sizeof(str)), ntohs(pin.sin_port), buf);
//just convert the characters to upper case
len = strlen(buf);
for (i=0; i buf[i] = toupper(buf[i]);
write(conn_fd, buf, len+1);
close(conn_fd);
}
return 0;
}
/*client.c
*socket client with error detect
* and sockopt
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAXLINE 80
int port = 8000;
int main(int argc, char *argv[])
{
struct sockaddr_in pin;
char buf[MAXLINE];
int sock_fd;
char str[MAXLINE];
char *myip = "127.0.0.1";
int n;
if (argc > 1)
{
myip = argv[1];
}
bzero(&pin, sizeof(pin));
pin.sin_family = AF_INET;
inet_pton(AF_INET, myip, &pin.sin_addr);
pin.sin_port = htons(port);
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if (sock_fd == -1)
{
perror("call to socket");
exit(1);
}
n = connect(sock_fd, (void*)&pin, sizeof(pin));
if (n == -1)
{
perror("call to connect");
exit(1);
}
while (fgets(str, MAXLINE, stdin) != NULL)
{
writeagain:
n = write(sock_fd, str, strlen(str) + 1);
if (n == -1)
{
if (errno == EINTR)
goto writeagain;
else
{
printf("call to write");
exit(1);
}
}
readagain:
n = read(sock_fd, buf, MAXLINE);
if (n == -1)
{
if (errno == EINTR)
goto readagain;
else
{
perror("call to read");
exit(1);
}
}else if (n == 0)
{
printf ("the other side has been closed.\n");
close(sock_fd);
}
printf("Response from server:%s\n", buf);
/*
if (n == 0)
printf("the other side has been closed.\n");
else
printf("Response from server:%s\n", buf);
*/
if (strncmp(str, "bye", 3) == 0)
break;
}
sleep(1);
n = close(sock_fd);
if (n == -1)
{
perror("call to close");
exit(1);
}
return 0;
}
/**
#########################################################
# Filename: server.c
# Description: select server
#########################################################
**/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAXLINE 80
int port = 8000;
int main (void)
{
struct sockaddr_in sin;
struct sockaddr_in pin;
int listen_fd;
int conn_fd;
int sock_fd;
int nready;
int client[FD_SETSIZE];
int maxi;
int maxfd;
fd_set rset;
fd_set allset;
int address_size;
char buf[MAXLINE];
char str[INET_ADDRSTRLEN]; // 16
int i;
int len;
int n;
bzero (&sin, sizeof (sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons (port);
listen_fd = socket (AF_INET, SOCK_STREAM, 0);
if (listen_fd == -1)
{
perror ("call to socket");
exit (1);
}
{
int opt = 1;
setsockopt (listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt));
}
n = bind (listen_fd, (struct sockaddr *) &sin, sizeof (sin));
if (n == -1)
{
perror ("call to bind");
exit (1);
}
n = listen (listen_fd, 20);
if (n == -1)
{
perror ("call to listen");
exit (1);
}
printf ("Accepting connections...\n");
maxfd = listen_fd;
maxi = -1;
for (i = 0; i < FD_SETSIZE; i++)
client[i] = -1;
FD_ZERO (&allset);
FD_SET (listen_fd, &allset);
for (;;)
{
rset = allset;
nready = select (maxfd + 1, &rset, NULL, NULL, NULL);
if (FD_ISSET (listen_fd, &rset))
{
address_size = sizeof (pin);
conn_fd =
accept (listen_fd, (struct sockaddr *) &pin, &address_size);
for (i = 0; i < FD_SETSIZE; i++)
{
if (client[i] < 0)
client[i] = conn_fd;
break;
}
if (i == FD_SETSIZE)
{
printf ("too many clients");
exit (1);
}
printf ("new client: %s, port %d\n",
inet_ntop (AF_INET, &pin.sin_addr, str, sizeof (str)),
ntohs (pin.sin_port));
FD_SET (conn_fd, &allset);
if (conn_fd > maxfd)
maxfd = conn_fd;
if (i > maxi)
maxi = i;
if (--nready <= 0)
continue;
}
for (i = 0; i <= maxi; i++)
{
if ((sock_fd = client[i]) < 0)
continue;
if (FD_ISSET (sock_fd, &rset))
{
n = read (sock_fd, buf, MAXLINE);
if (n == 0)
{
printf ("the other side has been closed.\n");
fflush (stdout);
close (sock_fd);
FD_CLR (sock_fd, &allset);
client[i] = -1;
}
else
{
printf ("received from client %d:%s\n", i, buf);
len = strlen (buf);
for (i = 0; i < len; i++)
buf[i] = toupper (buf[i]);
write (sock_fd, buf, len + 1);
}
if (--nready <= 0)
break;
}
}
}
}
/*udpclient.c*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAXLINE 80
int port = 8000;
int main(int argc, char *argv[])
{
struct sockaddr_in pin;
struct sockaddr_in rin;
char buf[MAXLINE];
int sock_fd;
char str[MAXLINE];
char sip[INET_ADDRSTRLEN];
int n;
int address_size;
bzero(&pin, sizeof(pin));
pin.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", &pin.sin_addr);
pin.sin_port = htons(port);
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (sock_fd == -1)
{
perror("call to socket");
exit(1);
}
while (fgets(str, MAXLINE, stdin) != NULL)
{
sendto(sock_fd, str, strlen(str) + 1, 0,
(struct sockaddr *)&pin, sizeof(pin));
if (n == -1)
{
perror("call to sendto.\n");
exit(1);
}
address_size = sizeof(rin);
n = recvfrom(sock_fd, buf, MAXLINE, 0, (struct sockaddr*)
&rin, &address_size);
if (n == -1)
{
perror("call to recvfrom.\n");
exit(1);
}else
{
printf("Response from %s port %d: %s\n",
inet_ntop(AF_INET, &rin.sin_addr, sip,
sizeof(sip)), ntohs(rin.sin_port),buf);
}
}
close(sock_fd);
if (n == -1)
{
perror("call to close. \n");
exit(1);
}
return 0;
}
/*udpserver.c*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAXLINE 80
int port =8000 ;
int main(void)
{
struct sockaddr_in sin;
struct sockaddr_in rin;
int sock_fd;
int address_size;
char buf[MAXLINE];
char str[INET_ADDRSTRLEN];
int i;
int n;
int len;
bzero(&sin,sizeof(sin));
sin.sin_family=AF_INET;
sin.sin_addr.s_addr=INADDR_ANY;
sin.sin_port =htons(port);
sock_fd= socket(AF_INET,SOCK_DGRAM,0);
if(sock_fd== -1){
perror("call to socket");
exit(1);
}
n=bind(sock_fd,(struct sockaddr *) &sin,sizeof(sin));
if(n == -1){
perror("call to bind");
exit(1);
}
while(1)
{
address_size=sizeof(rin);
n =recvfrom(sock_fd,buf,MAXLINE,0,(struct sockaddr *) &rin,
&address_size);
if( n == -1){
perror("call to recvfrom.\n");
exit(1);
}
printf("received from client %s at port %d: %s\n",
inet_ntop(AF_INET , &rin.sin_addr,str,
sizeof(str)),ntohs(rin.sin_port),buf);
//just convert the characters to upper case
len =strlen(buf);
for (i=0; i buf[i]=toupper(buf[i]);
n =sendto(sock_fd,buf,len +1,0,
(struct sockaddr *) &rin,address_size);
if( n== -1){
perror("call to sendto.\n");
exit(1);
}
}
}
/*unblkserver.c
*unblock socket server*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAXLINE 80
int port = 8000;
int main(void)
{
struct sockaddr_in sin;
struct sockaddr_in rin;
int sock_fd;
int address_size;
char buf[MAXLINE];
char str[INET_ADDRSTRLEN];
int i;
int n;
int len;
long flags;
bzero(&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(port);
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (sock_fd == -1)
{
perror("call to bind");
exit(1);
}
n = bind(sock_fd, (struct sockaddr *)&sin, sizeof(sin));
if (n == -1)
{
perror("call to bind");
exit(1);
}
flags = fcntl(sock_fd, F_GETFL);
flags |= O_NONBLOCK;
if (fcntl(sock_fd, F_SETFL, flags) == -1)
{
perror("trying to set sock_fd to non-blocking");
exit(1);
}
printf("sock_fd has been set to non-blocking mode.\n");
while (1)
{
sleep(3);
address_size = sizeof(rin);
n = recvfrom(sock_fd, buf, MAXLINE, 0, (struct sockaddr*)
&rin, &address_size);
if (n == -1 && errno != EAGAIN)
{
perror("call to recvfrom");
exit(1);
}else if (n == 0 || (n == -1 && errno == EAGAIN))
{
printf("no data yet\n");
continue;
}else
{
printf("received from client %s at port %d: %s\n",
inet_ntop(AF_INET, &rin.sin_addr, str,
sizeof(str)), ntohs(rin.sin_port), buf);
}
//just convert
len = strlen(buf);
for (i = 0; i < len; i++) buf[i] = toupper(buf[i]);
n = sendto(sock_fd, buf, len+1, 0, (struct sockaddr*)
&rin, address_size);
if (n == -1 && errno != EAGAIN)
{
perror("call to sendto");
exit(1);
}
}
}
/*client80.c
*a program to get html from internet
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAXLINE 1024
int port = 80;
int main(int argc, char *argv[])
{
FILE *fp;
int sock_fd, ret;
struct sockaddr_in pin;
char buf[MAXLINE + 1];
char *str = "GET / HTTP/1.1\n HOST:\n\n";
char *myip = "202.108.9.31"; //
if (argc > 1)
{
myip = argv[1];
}
if ((fp = fopen("163.html", "w+")) == NULL)
{
printf("Cannot open 163.html");
exit(1);
}
bzero(&pin, sizeof(pin));
pin.sin_family = AF_INET;
inet_pton(AF_INET, myip, &pin.sin_addr);
pin.sin_port = htons(port);
sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock_fd == -1)
{
perror("call to socket");
exit(1);
}
ret = connect(sock_fd, (void*)&pin, sizeof(pin));
if (ret == -1)
{
perror("call to connect");
goto PROGRAM_EXIT;
}
WRITE_AGAIN:
ret = write(sock_fd, str, strlen(str));
if (ret == -1)
{
if (errno == EINTR)
goto WRITE_AGAIN;
else
{
printf("call to write");
goto PROGRAM_EXIT;
}
}
/* read data from server */
while(1)
{
READ_AGAIN:
ret = read(sock_fd, buf, MAXLINE);
if (ret > 0)
{
buf[ret] = '\0';
printf("Response from server:%s\n", buf);
fprintf(fp, "%s", buf);
}
else if (ret == -1)
{
if (errno == EINTR)
goto READ_AGAIN;
else
{
perror("call to read");
goto PROGRAM_EXIT;
}
}
else if (ret == 0)
{
printf ("the other side has been closed.\n");
break;
}
}
PROGRAM_EXIT:
close(sock_fd);
fclose(fp);
return 0;
}
/*domainsoc.c
*UNIX Domain Socket IPC
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(void)
{
int fd, size;
struct sockaddr_un un;
un.sun_family = AF_UNIX;
strcpy(un.sun_path, "foo.socket");
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) <0) {
perror( "socket failed" );
exit(1);
}
size = offsetof(struct sockaddr_un, sun_path) + strlen(un.sun_path);
if (bind(fd, (struct sockaddr *)&un, size)< 0) {
perror( "bind failed" );
exit(1);
}
printf( "UNIX domain socket bound\n" );
exit(0);
}
/*domainserver1.c
*UNIX Domain Socket IPC
*accept->serv_accept
*/
#include
#include
#include
#include
#include
#include
#define STALE 30
#define QLEN 10
int serv_accept(int listenfd, uid_t *uidptr)
{
int clifd, len, err, rval;
time_t staletime;
struct sockaddr_un un;
struct stat statbuf;
len = sizeof(un);
if ((clifd = accept(listenfd, (struct sockaddr *)&un, &len)) < 0)
return (-1);
len -= offsetof(struct sockaddr_un, sun_path);
un.sun_path[len] = 0;
if (stat(un.sun_path, &statbuf) <0) {
rval = -2;
goto errout;
}
#ifdef S_ISSOCK
if (S_ISSOCK(statbuf.st_mode) == 0) {
rval = -3;
goto errout;
}
#endif
if ((statbuf.st_mode & (S_IRWXG | S_IRWXO)) ||
(statbuf.st_mode & S_IRWXU) != S_IRWXU) {
rval = -4;
goto errout;
}
staletime = time(NULL) - STALE;
if (statbuf.st_atime < staletime ||
statbuf.st_ctime < staletime ||
statbuf.st_mtime < staletime) {
rval = -5;
goto errout;
}
if(uidptr != NULL)
*uidptr = statbuf.st_uid;
unlink(un.sun_path);
return(clifd);
errout:
err = errno;
close(clifd);
errno = err;
return(rval);
}
/*domainserver.c
*UNIX Domain Socket IPC
*listen->serv_listen
*/
#include
#include
#include
#include
#define QLEN 10
int serv_listen(const char *name)
{
int fd, len, err, rval;
struct sockaddr_un un;
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
return (-1);
unlink(name);
memset(&un, 0, sizeof(un));
un.sun_family = AF_UNIX;
strcpy(un.sun_path, name);
len = offsetof(struct sockaddr_un, sun_path) + strlen(name);
if (bind(fd, (struct sockaddr *)&un, len) <0) {
rval = -2;
goto errout;
}
if (listen(fd, QLEN) < 0) {
rval = -3;
goto errout;
}
return 0;
errout:
err = errno;
close(fd);
errno = err;
return(rval);
}
/*domainclient.c
*unix domain socket IPC
*connect->cli_conn
*/
#include
#include
#include
#include
#include
#include
#define CLI_PATH "/var/tmp/"
/* +5 for pid =14 char */
#define CLI_PERM S_IRWXU
/* rwx for user only */
/*
* Creat a client endpoint and connect to a server .
* Return fd if all OK ,<0 on error .
*/
int cli_conn(const char *name)
{
int fd,len,err,rval ;
struct sockaddr_un un;
/*creat a UNIX domain stream socket */
if((fd =socket( AF_UNIX,SOCK_STREAM,0 ))< 0)
return (-1);
/* fill socket address structure with our address */
memset(&un ,0, sizeof(un));
un.sun_family=AF_UNIX;
sprintf(un.sun_path,"%s%05d",CLI_PATH,getpid());
len =offsetof(struct sockaddr_un,sun_path)+strlen(un.sun_path);
unlink(un.sun_path); /* in case it already exists */
if(bind(fd,(struct sockaddr *)&un,len)<0){
rval =-2;
goto errout;
}
if(chmod(un.sun_path, CLI_PERM)< 0){
rval = -3;
goto errout;
}
/* fill socket address structure with server's address */
memset(&un,0,sizeof(un));
un.sun_family =AF_UNIX;
strcpy(un.sun_path,name);
len =offsetof(struct sockaddr_un ,sun_path) +strlen(name);
if(connect(fd, (struct sockaddr *)&un, len)<0) {
rval =-4;
goto errout;
}
return (fd);
errout:
err = errno;
close(fd);
errno = err;
return(rval);
}
信息点滴:
端口号信息可以查看/etc/services.
/etc/resolv.conf 域名服务器设置;
/etc/hosts ? 过滤网站
ps aux | less
netstat -a | grep :80
rpm -ivh --nodeps -force name.rpm
/usr/share/applications 应用程序菜单所在
slash->/ period->. comma->,
^ +. 切换全角半角中文