Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5512
  • 博文数量: 2
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 10
  • 用 户 组: 普通用户
  • 注册时间: 2015-03-16 12:04
文章分类
文章存档

2015年(2)

我的朋友
最近访客

分类: LINUX

2015-04-30 17:25:06

原文地址:linux学习杂记_socket编程 作者:ali_tong


网络的一些相关知识:
网卡功能: 载波侦听, 冲突检测, 随机延时等待;
网线一般不得超过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->,
^ +.   切换全角半角中文

阅读(628) | 评论(0) | 转发(0) |
0

上一篇:#if, #elif, #else, #endif 使用

下一篇:没有了

给主人留下些什么吧!~~