注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Under the bule sky

Get what I want "cause I ask for it.

 
 
 

日志

 
 

网络编程相关API  

2014-08-17 14:36:49|  分类: 默认分类 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
一、IP地址转换函数

网络编程相关API - 戴↑Ω听歌 - Under the bule sky

//将"192.168.0.3"点分十进制ip字符串转为网络字节序的无符号整型ip数值(大端)
int inet_aton(const char *cp, struct in_addr *inp);
in_addr_t inet_addr(const char *cp);

//网络字节序的无符号整型ip数值将转为"192.168.0.3"点分十进制ip字符串
char *inet_ntoa(struct in_addr in);
测试代码:

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

//./a.out 192.168.0.127
int main(int argc, const char *argv[])
{
struct in_addr ip_addr;

if(argc < 2)
{
fprintf(stderr,"Usage %s ip\n",argv[0]);
exit(EXIT_FAILURE);
}

printf("ip:\t%#X\n",inet_addr(argv[1]));
printf("ip:\t%#X\n",ntohl(inet_addr(argv[1])));

puts("===========================================");

if(inet_aton(argv[1],&ip_addr) == 0)
{
printf("address is invalid\n");
exit(EXIT_FAILURE);
}

printf("ip:\t%s\n",argv[1]);
printf("ip:\t%#x\n",ip_addr.s_addr);
printf("ip:\t%#x\n",ntohl(ip_addr.s_addr));

printf("IP:\t%s\n",inet_ntoa(ip_addr));


return 0;
}



结果:
网络编程相关API - 戴↑Ω听歌 - Under the bule sky
 


二、字节序转换函数

网络编程相关API - 戴↑Ω听歌 - Under the bule sky
 
主机字节序转网络字节序 

  l表示unsigned long类型 
  uint32_t htonl(uint32_t hostlong); 
  s表示unsigned short类型 
  uint16_t htons(uint16_t hostshort); 
  网络字节序转主机字节序 

  uint32_t ntohl(uint32_t netlong); 
  uint16_t ntohs(uint16_t netshort);

三、创建套接字

网络编程相关API - 戴↑Ω听歌 - Under the bule sky
 
int socket(int domain, int type, int protocol);
功能:新建socket
参数:
    domain       地址族:
AF_INET,AF_UNIX,AF_INET6
    type         套接字类型:
SOCK_STREAM (tcp),SOCK_DGRAM (udp) SOCK_RAW
    protocol     0
返回值:成功返回socket文件描述符;失败返回-1,置errno


socket 相关地址结构
通用地址结构
struct sockaddr
{    
    u_short  sa_family;    // 地址族, AF_xxx
    char  sa_data[14];     // 14字节协议地址
};

Internet协议地址结构        
struct sockaddr_in  
{           
    u_short sin_family;      // 地址族, AF_INET,2 bytes
    u_short sin_port;      // 端口,2 bytes
    struct in_addr sin_addr;  // IPV4地址,4 bytes     
    char sin_zero[8];        // 8 bytes unused,作为填充,
               // 保证sizeof(struct sockaddr_in) == sizeof(struct sockaddr)
}; 

IPv4地址结构
// internet address  
struct in_addr
{
    in_addr_t  s_addr;            // u32 network address 
};

四、绑定地址

网络编程相关API - 戴↑Ω听歌 - Under the bule sky
 
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
功能:绑定地址
参数:
    sockfd:     socket调用返回的文件描述符  
    addr:       填充好的socket要绑定的地址结构首地址
    addrlen:     sockaddr地址结构的长度

返回值:0或-1,置错误码

//定义通用socket地址类型别名
typedef struct sockaddr sa_t;

{
    struct sockaddr_in my_addr;

    memset(&my_addr,0,sizeof(my_addr));
    my_addr.sin_family = AF_INET;//地址族或协议族
    my_addr.sin_port = htons(atoi(argv[2]));//网络字节序的端口号
    my_addr.sin_addr.s_addr = inet_addr(argv[1]);//网络字节序的ip地址

    if(bind(sockfd,(sa_t *)&my_addr,sizeof(sa_t)) < 0)
}

五、将socket设置为监听socket (服务器端)

网络编程相关API - 戴↑Ω听歌 - Under the bule sky
 
int listen(int sockfd, int backlog);
功能: 将socket设为监听模式
参数:
    sockfd:     监听连接的套接字
    backlog:     指定了正在等待连接的最大队列长度,它的作用在于处理可能同时出现的几个连接请求。
返回值: 成功返回0;失败返回-1,置errno

完成listen()调用之后,socket变成了监听socket。

六、提取等待连接队列中请求 server端

网络编程相关API - 戴↑Ω听歌 - Under the bule sky
 
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
功能:提取等待连接队列中请求,创建新的己连接socket用于通信
参数:
        sockfd :    监听套接字 
        addr :      对方地址
        addrlen:   地址长度,需要先初始化addrlen,再传其首地址
返回值:成功返回新socket fd;失败返回-1,置errno


七、客户端向服务器端发起连接请求 client端

网络编程相关API - 戴↑Ω听歌 - Under the bule sky
 
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
功能:客户端向服务器端发起连接请求
参数:
        sockfd : socket返回的文件描述符
        serv_addr : 服务器端的地址信息  
        addrlen : serv_addr的长度 
返回值:成功返回0;失败返回-1,置errno

例:./client  192.168.0.3  8888
             argv[1]      argv[2]

//定义通用socket地址类型别名
typedef struct sockaddr sa_t;

{
    struct sockaddr_in server_addr;

    memset(&server_addr,0,sizeof(server_addr));
    server_addr.sin_family = AF_INET;//地址族或协议族
    server_addr.sin_port = htons(atoi(argv[2]));//网络字节序的端口号
    server_addr.sin_addr.s_addr = inet_addr(argv[1]);//网络字节序的ip地址

    if(connect(sockfd,(sa_t *)&server_addr,sizeof(sa_t)) < 0)

}


//tcp发送与接收,用法类似read/write
ssize_t  send(int  socket,  const  void  *buffer,  size_t  length, int flags);
ssize_t  recv(int  socket,  void  *buffer,  size_t  length, int flags);



TCP协议:
服务器端与客户端通信实例:
服务器端代码:
server.c
网络编程相关API - 戴↑Ω听歌 - Under the bule sky
 

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define BACKLOG 128
#define N 1024

#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)

typedef struct sockaddr sa_t;


//./a.out 192.168.0.xxx 8888
int main(int argc, const char *argv[])
{
int n = 0;
char buf[N] = {0};
int listen_fd = 0,sockfd = 0;
struct sockaddr_in server_addr,peer_addr;
socklen_t addrlen = sizeof(struct sockaddr_in);


if(argc < 3)
{
fprintf(stderr,"Usage %s ip port\n",argv[0]);
exit(EXIT_FAILURE);
}

//TODO step1 int socket(int domain, int type, int protocol);
if((listen_fd = socket(AF_INET,SOCK_STREAM,0)) < 0)
handle_error("socket");

memset(&server_addr,0,sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(atoi(argv[2]));
server_addr.sin_addr.s_addr = inet_addr(argv[1]);

//TODO step2 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
if(bind(listen_fd,(sa_t *)&server_addr,sizeof(sa_t)) < 0)
handle_error("bind");

//TODO step3 int listen(int sockfd, int backlog);
if(listen(listen_fd,BACKLOG) < 0)
handle_error("listen");

printf("listenning ...\n");

while(1)
{
//TODO step4 int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
if((sockfd = accept(listen_fd,(sa_t *)&peer_addr,&addrlen)) < 0)
handle_error("accept");

printf("sockfd = %d\n",sockfd);

printf("===============================\n");
printf("IP:\t%s\n",inet_ntoa(peer_addr.sin_addr));
printf("PORT:\t%d\n",ntohs(peer_addr.sin_port));
printf("===============================\n");

n = recv(sockfd,buf,sizeof(buf) - 1,0);
buf[n] = '\0';
printf("Receive %d bytes:%s\n",n,buf);

}


return 0;
}



客户端代码:
client.c

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define BACKLOG 128
#define N 1024

#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)

typedef struct sockaddr sa_t;


//./a.out 192.168.0.xxx 8888
int main(int argc, const char *argv[])
{
int n = 0;
char buf[N] = {0};
int sockfd = 0;
struct sockaddr_in server_addr,peer_addr;
socklen_t addrlen = sizeof(struct sockaddr_in);


if(argc < 3)
{
fprintf(stderr,"Usage %s ip port\n",argv[0]);
exit(EXIT_FAILURE);
}

//TODO step1 int socket(int domain, int type, int protocol);
if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
handle_error("socket");

memset(&server_addr,0,sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(atoi(argv[2]));
server_addr.sin_addr.s_addr = inet_addr(argv[1]);


if(connect(sockfd,(sa_t *)&server_addr,sizeof(sa_t)) < 0)
handle_error("connect");

send(sockfd,"hello server!",13,0);

#if 0
n = recv(sockfd,buf,sizeof(buf) - 1,0);
buf[n] = '\0';
printf("Receive %d bytes:%s\n",n,buf);
#endif
close(sockfd);


return 0;
}



运行结果:
服务器先启动:
网络编程相关API - 戴↑Ω听歌 - Under the bule sky
  客户端启动:
网络编程相关API - 戴↑Ω听歌 - Under the bule sky
服务器端显示结果:
网络编程相关API - 戴↑Ω听歌 - Under the bule sky
  


UDP协议:

udp数据包的收发sendto/recvfrom

发送
//tcp
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
//udp
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
    const struct sockaddr *dest_addr, socklen_t addrlen);
    //向指定地址发送                  //地址结构大小

接收
//tcp
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
//udp
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
    struct sockaddr *src_addr, socklen_t *addrlen);
    //接收发送方地址           //发送方地址结构长度
    
udp与tcp流程对比
服务器端 udp无listen() , accept()
客户端   udp也可选的使用connect()指定接收方的,而不是tcp中向服务器发起连接指定后可使recv()/send()收发数据,在udp客户端可connect()多次

udp与tcp读写数据对比
udp读写 recvfrom(,接收对方地址结构,对方地址结构大小)
          sento(,    指向接收方地址,接收方地址结构大小);
          如果udp客户端connect()也可使用recv()/send() read()/write()
tcp读写:
recv();    read();send();    write();




服务器与客户端流程
网络编程相关API - 戴↑Ω听歌 - Under the bule sky
 
网络编程相关API - 戴↑Ω听歌 - Under the bule sky
 
代码:
头文件 head.h

#ifndef _HEAD_H_
#define _HEAD_H_

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h> /* See NOTES */
#include <sys/stat.h>
#include <fcntl.h>

#define BUF_SZ 1024

#define handle_error(msg) \
do {perror(msg); exit(EXIT_FAILURE);} while(0)

typedef struct sockaddr sa_t;


#endif



服务器端代码:
server.c

#include "head.h"

int main(int argc, const char *argv[])
{
int n = 0;
int sockfd = 0;
char buf[BUF_SZ] = {0};
socklen_t addrlen = sizeof(sa_t);
struct sockaddr_in peer_addr;
struct sockaddr_in server_addr;

if (argc < 3)
{
fprintf(stderr,"Usage %s ip port\n",argv[0]);
exit(EXIT_FAILURE);
}

if((sockfd = socket(AF_INET,SOCK_DGRAM,0)) < 0)
handle_error("socket");

bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(atoi(argv[2]));
server_addr.sin_addr.s_addr = inet_addr(argv[1]);

if(bind(sockfd,(sa_t *)&server_addr,sizeof(sa_t)) < 0)
handle_error("bind");

while(1)
{
n = recvfrom(sockfd,buf,sizeof(buf) - 1,0,(sa_t *)&peer_addr,&addrlen);
buf[n] = '\0';

puts("=================================");
printf("Ip:\t%s\n",inet_ntoa(peer_addr.sin_addr));
printf("Port:\t%d\n",ntohs(peer_addr.sin_port));
printf("Info:\t%s\n",buf);
puts("=================================");


}



return 0;
}


客户端代码:
client.c

#include "head.h"

int main(int argc, const char *argv[])
{
int n = 0;
int sockfd = 0;
char buf[BUF_SZ] = {0};
socklen_t addrlen = sizeof(sa_t);
struct sockaddr_in peer_addr;
struct sockaddr_in server_addr;

if (argc < 3)
{
fprintf(stderr,"Usage %s ip port\n",argv[0]);
exit(EXIT_FAILURE);
}

if((sockfd = socket(AF_INET,SOCK_DGRAM,0)) < 0)
handle_error("socket");

bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(atoi(argv[2]));
server_addr.sin_addr.s_addr = inet_addr(argv[1]);

while(1)
{
putchar('>');
fgets(buf,sizeof(buf),stdin);

n = sendto(sockfd,buf,strlen(buf),0,(sa_t *)&server_addr,sizeof(sa_t));
}



return 0;
}


注意:先运行服务器
运行结果如下:
网络编程相关API - 戴↑Ω听歌 - Under the bule sky
 
网络编程相关API - 戴↑Ω听歌 - Under the bule sky
 





  评论这张
 
阅读(26)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017