linux之小白都懂的网络编程

一、为什么要使用网络编程
五种进程间通信的方式都是基于linux内核的单机通信,无法完成多机之间的通信,而网络编程,socket,可以实现多机之间的通信,很容易完成服务器与客户端之间的通信。
二、TCP协议与UDP协议
TCP是面向连接的;UDP是无连接的,发送数据之前不需要建立连接。
TCP提供可靠服务,即通过TCP建立连接发送的数据,无差错,无丢失,无重复,按序传送;UDP则是尽最大努力交付,不可靠传输。
TCP是面向字节流;UDP是面向报文的,UDP没有拥塞控制,即网络面对拥塞不会使源主机发送速率降低。
TCP连接是点对点的;UDP支持一对一、一对多、多对一和多对多交互通信。
TCP首部开销大,20个字节;UDP首部开销小,8个字节。
TCP的逻辑通信信道是全双工的可靠信道;UDP是不可靠信道。
三、端口号的作用
一台PC机只有一个IP地址,但可以完成许多服务,web服务、ftp服务等,主机显然不能通过一个ip地址区分这么多服务,而端口提供了一种访问通道,通过ip地址和端口号,便可以精确访问某个服务。
四、字节序
概念:字节序是指多字节数据在计算机内存中存储,或者网络传输时各字节的存储顺序。
Little endian 小端字节序:是将低序的字节存储在起始位置
Big endian 大端字节序:是将高序的字节存储在起始位置
网络字节序=大端字节序
举个例子 ,理解一下
内存中有0x01020304的存储方式
其中01为高序字节,04为低序字节
内存地址有4000&4001&4002&4003
大端字节序是指,01高序字节存储在4000的内存中,其余依次排列
小端字节序是指,04低序字节存储在4000的内存中,其余依次排列
五、网络编程API概要
1、函数原型

服务器相关api
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
//1、创建套接字,成功返回套接字描述符,失败返回-1
int socket(int domain, int type, int protocol);
参数一:使用的协议族 通常有 AF_INET(IPv4) AF_INET6(IPv6)两个宏
参数二:使用的协议类型 通常有 SOCK_STREAM(TCP协议) SOCK_DGRAM(UDP协议)两个宏
参数三:通常赋值为0,选择与type类型相对应的协议
//2、绑定ip地址和相对应的端口,成功返回0,失败返回-1
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
参数一:socket返回的套接字描述符
参数二:是一个结构体配置ip地址相关信息
参数三:结构体的大小
参数二的结构体 通常用另一个结构体替代,需要做结构体类型的强制转换
struct sockaddr_in {
  __kernel_sa_family_t  sin_family;     /* 协议族            */
  __be16                sin_port;       /* 端口号            */
  struct in_addr        sin_addr;       /* IP地址结构体       */
   unsigned char        sin_zero[8]     /*填充 没有实际意义*/
   };
   struct in_addr {
        __be32  s_addr;
};
//3、监听是否有客户端访问
int listen(int sockfd, int backlog);
参数二:监听的个数
//4、用来接受已连接的客户端,成功返回一个通道id用于后续 write read操作,失败返回-1
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数二:用来返回已连接客户端的IP地址
参数三:客户端IP地址的大小
//IP地址转换的api
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int inet_aton(const char *cp, struct in_addr *inp);
将字符串“192.168.1.1”形式转换为网络识别的格式
char *inet_ntoa(struct in_addr in);
将网络格式的IP地址转换为字符串形式
//字节序转化api
#include <arpa/inet.h>
uint16_t htons(uint16_t hostshort)//返回网络字节序的值
uint32_t htonl(uint32_t hostlong);//返回网络字节序的值
 uint32_t ntohl(uint32_t netlong);//返回主机字节序的值
 uint16_t ntohs(uint16_t netshort);//返回主机字节序的值
//5、数据收发 
read write &recv send 一般用于TCP
recvmsg sendmsg &recvfrom sendto 一般用于UDP
客户端相关api
//1、创建套接字,成功返回套接字描述符,失败返回-1
int socket(int domain, int type, int protocol);
//2、连接服务器
 int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
 参数二:服务器的IP地址和端口对应的结构体指针
 参数三:地址长度,结构体大小

服务器demo

//sever.c
#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
int main()
{
        int sockid;
        int s_id;
        char readBuf[256];
        struct sockaddr_in saddr;//服务器IP地址结构体
        struct sockaddr_in caddr;//客户端IP地址结构体
        saddr.sin_family = AF_INET;
        saddr.sin_port  = htons(8888);//配置服务器端口
        inet_aton("192.168.1.101",&saddr.sin_addr);//服务器地址
        sockid=socket(AF_INET ,SOCK_STREAM,0);
        if(sockid==-1)
        {
                printf("socket error\n");
                exit(-1);
        }
        bind(sockid,(struct sockaddr *)&saddr,sizeof(struct sockaddr_in));
        listen(sockid,8);//监听socket
        int addrlen  =sizeof(struct sockaddr_in);
        while(1)//不断的接受客户端的连接
        {
                s_id=accept(sockid,(struct sockaddr *)&caddr,&addrlen);
                //接受客户端socket返回通道id
                printf("client ip addr is %s\n",inet_ntoa(caddr.sin_addr));
                write(s_id,"hello client",15);//往客户端写数据
                read(s_id,readBuf,sizeof(readBuf));//从客户端读数据
                printf("from client:%s\n",readBuf);
        }
        return 0;
}

客户端demo

//client.c
#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main()
{       
        int sockid;
        struct sockaddr_in saddr;//连接的服务器的IP地址结构体
        char readBuf[128];
        saddr.sin_family = AF_INET;
        saddr.sin_port  = htons(8888);
        inet_aton("192.168.1.101",&saddr.sin_addr);
        sockid = socket(AF_INET,SOCK_STREAM ,0);
        if(sockid == -1)
        {
                printf("socket error\n");
                exit(-1);
        }
        connect(sockid,(struct sockaddr *)&saddr,sizeof(struct sockaddr_in));//连接服务器
        read(sockid,readBuf,sizeof(readBuf));//读服务器的数据
        write(sockid,"i am client",128);//给服务器发送数据
        printf("receive context %s\n",readBuf);
        return 0;
}
执行结果
sever:
client ip addr is 192.168.1.101
from client:i am client

client:
receive context hello client
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值