linux-基础-网络

大纲:
1.linux网络概述
2.网络编程基础
3.网络编程实例
一.linux网络概述
1.linux优势
1)完善内置网络
2)提供大量支持internet的免费软件
3)用户可以通过linux命令来完成内部信息和文件传输
4)远程访问
5)安全可靠
2.linux网络模型—–TCP/IP4层
应用层(telnet,文件传输协议–ftp,tftp,smtp,dns)
传输层(传输控制协议–TCP,用户数据报文协议–UDP)
网络层(internet协议–IP,网络控制报文协议–ICMP和地址解析协议–ARP)
网络接口层
二.网络编程的基础
1.linux网络编程通过socket实现,socket是一种文件描述符
socket有三种类型
1)流式套接字(TCP/IP协议)(SOCK_STREAM)
2)数据报套接字(SOCK_DGRAM)使用UDP协议
3)原始套接字(SOCK_RAW)使用IP协议,用于新网络协议测试
2.在socket程序中,struct sockaddr用于记录网络地址
struct sockaddr{
u_short sa_family; //协议族,采用”AF_xxx”,如AF_INET(IP协议族)
char sa_data[14]; //14字节的特定协议地址
};
3.在socket程序设计中,struct socketaddr_in同样用于记录网络地址
struct sockaddr_in {
short int sin_family; /* 地址族 */
unsigned short int sin_port; /* 端口号 */
struct in_addr sin_addr; /* 协议特定地址 */
unsigned char sin_zero[8]; /* 填0 */
};
struct in_addr
struct in_addr {
unsigned long s_addr;
};
或者
typedef struct in_addr{
union{
struct{
unsigned char s_b1,s_b2,s_b3,s_b4;
} S_un_b;
struct{
unsigned short s_w1,s_w2;
} S_un_w;
unsigned long S_addr;//成员s_addr为长整形结构
} S_un;
}IN_ADDR;
编程中一般使用sockaddr等价于sockaddr_in数据结构
通常IP形式是192.168.0.29,在struct in_addr的ip为32位整数
使用函数转化
int inet_aton(const char*cp,struct in_addr *inp)
char *inet_ntoa(struct in_addr in)
a表示ascii码,n表示network
inet_aton—-将a.b.c.d形式转为32位ip形式存储在inp指针里面
inet_ntoa—-将32位ip转为a.b.c.d
4.字节转换
网络字节传输顺序(big endian)
htons(unsigned short–>网络序)
ntons(网络序–>主机序)
htonl(unsigned long–>网络序)
ntonl(网络序–>主机序)
5.在网络中标识一台主机可以是ip地址,也可以是主机名
stuct hostent *gethostbyname(const char *hostname)
这个函数的传入值是域名或者主机名,例如”www.baidu.com”等等。
传出值,是一个hostent的结构。如果函数调用失败,将返回NULL。
需要包含的头文件

#include 
#include 

返回值hostent结构体指针
struct hostent
{
char *h_name; //主机名
char **h_aliases;//主机别名
int h_addrtype;//主机地址类型AF_INET
int h_length;//主机地址长度
char **h_addr_list;//主机IP地址列表
#define h_addr h_addr_list[0]//主机第一个IP地址
};
6.socket编程步骤
1)socket创建
int socket(int protofamily, int type, int protocol);//返回sockfd-描述符
protofamily:协议族(family)。常用的协议族有,AF_INET(IPV4)、AF_INET6(IPV6)、AF_LOCAL(或称AF_UNIX,Unix域socket)、AF_ROUTE等等。协议族决定了socket的地址类型,在通信中必须采用对应的地址
type:指定socket类型。
常用的socket类型有:
SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等
protocol:指定协议。
常用的协议有:IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议
SOCK_STREAM不可以跟IPPROTO_UDP组合。当protocol为0时,会自动选择type类型对应的默认协议。
2)bind绑定ip和端口号到socket
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd:socket描述字,它是通过socket()函数创建
addr:一个const struct sockaddr *指针,指向要绑定给sockfd的协议地址,根据地址协议不同创建函数也不同struct sockaddr_in
addrlen:对应的是地址的长度
3)connect与服务器建立连接
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
4)listen设置服务器最大连接数
int listen(int sockfd, int backlog);
5)accpet等待客户端socket连接请求
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); //返回连接connect_fd
6)send发送数据
7)recv接收数据
7.基于TCP程序设计步骤
a.服务器端
1)创建一个socket,用socket()
2)绑定IP地址,端口信息到socket,bind()
3)设置最大允许连接数listen()
4)等待客户端请求accept()
5)发送数据send(),recv()或者read(),write()
6)关闭网络连接
b.客户端
1)创建一个socket,用socket()
2)绑定IP地址,端口信息到socket,bind()
3)连接服务器connect()
4)发送数据send(),recv()或者read(),write()
read(),write()这些函数在之前IO口文件操作的章节已经介绍过啦
5)关闭网络连接
8.基于UDP程序设计步骤
a.服务器端
1)创建一个socket,用socket()
2)绑定IP地址,端口信息到socket,bind()
3)循环接收数据recvfrom()
4)关闭网络连接
int close(int fd);
b.客户端
1)创建一个socket,用socket()
2)绑定IP地址,端口信息到socket,bind()
3)设置对方的ip地址和端口信息
4)发送数据sendto()
5)关闭网络连接
三.网络编程实例
客户端

#include 
#include 
#include  
#include 
#include
#include 
#include 
#define portnumber 3333
int main(int argc,char *argv[]){
int sockfd;
char buffer[1024];
struct sockaddr_in server_addr;
struct hostent *host;
if(argc!=2){
   fprintf(stderr,"usage:%s hostname\n",argv[0]);
   exit(1);
   }
/*if(host=gethostbyname(argv[1])==NULL){//获取主机名
   fprintf(stderr,"get hostname error\n");
   exit(1);
   }*/
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1){//创建socket
   fprintf(stderr,"socket error:%s\n",strerror(errno));
   exit(1);
   }
bzero(&server_addr,sizeof(server_addr));/*void _bzero (void *s, size_t len);将s的前len字节设为0==>这里是把server_addr内存地址清空*,和memset一样*/
   server_addr.sin_family=AF_INET;//地址簇
   server_addr.sin_port=htons(portnumber);//端口号
//   server_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
//   server_addr.sin_addr=*((struct in_addr*)host->h_addr);//协议特定地址
#if 1
if(inet_pton(AF_INET,argv[1],&server_addr.sin_addr)<=0){
   printf("inet_pton error for %s\n",argv[1]);
   exit(1);
   }
#endif
if (connect(sockfd,(struct sockaddr*)(&server_addr),sizeof(struct sockaddr_in))==-1){//连接服务器
   perror("connect error");
   exit(1);
   }
printf("connect success\n");
fgets(buffer,1024,stdin);//stdin--标准输入流,就是键盘,读一行字符串(长度 <= 1024),包括换行键,存入buffer
write(sockfd,buffer,strlen(buffer));//将strlen(buffer)个字节长度的数据从buffer读到文件描述符sockfd中
close(sockfd);//关闭网络连接
exit(0);
}

服务器端

#include 
#include 
#include  
#include 
#include
#include 
#include 
#define portnumber 3333
int main(int argc,char *argv[]){
  int sockfd,new_fd;
  struct sockaddr_in server_addr;
  struct sockaddr_in client_addr;
  int sin_size;
  int nbytes;
  char buffer[1024];
  if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1){//创建socket
     fprintf(stderr,"socket error:%s\n",strerror(errno));
     exit(1);
   }
  bzero(&server_addr,sizeof(server_addr));
  server_addr.sin_family=AF_INET;//地址簇
  server_addr.sin_addr.s_addr=htonl(INADDR_ANY);//IP地址设置成INADDR_ANY,让系统自动获取本机的IP地址。
  server_addr.sin_port=htons(portnumber);//端口号
  if(bind(sockfd,(struct sockaddr*)(&server_addr),sizeof(struct sockaddr_in))==-1){
     printf("bind error:%s\n",strerror(errno));
     exit(1);
   }
  if(listen(sockfd,5)==-1){
     printf("listen error\n");
     exit(1);
   }
printf("=======wait=========\n");
  while(1){
     sin_size=sizeof(struct sockaddr_in);
         if((new_fd=accept(sockfd,(struct sockaddr*)(&client_addr),(socklen_t*)&sin_size))==-1){
           printf("accept error\n");
           exit(1);
           }
     printf("accept success\n");
     if((nbytes=read(new_fd,buffer,1024))==-1){
           printf("read error\n");
           exit(1);
         }
        buffer[nbytes]='\0';
  printf("success\n");
  close(new_fd);
}

测试结果
linux-基础-网络_第1张图片

你可能感兴趣的:(Linux,c,网络编程,socket)