linux-C编程-网络编程

本文详细介绍了Linux网络编程,涵盖了OSI七层模型和TCP/IP五层模型,重点讲解了TCP三次握手和四次挥手的过程。还深入讨论了socket编程,包括不同类型的网络传输及函数使用,如socket、bind、listen、accept、connect、read、write等,并提到了网络字节序和主机字节序的转换函数。此外,还讨论了多客户编程中的阻塞与非阻塞模型,以及select、poll、epoll等多路复用技术。
摘要由CSDN通过智能技术生成

3,linux网络编程

三元组(ip地址,协议,端口)就可以标识网络的进程

3.1,OSI七层模型和TCP/IP五层模型

OSI七层网络模型由下至上为1至7层,分别为:

物理层(Physical layer),数据链路层(Data link layer),网络层(Network layer),传输层(Transport layer),会话层(Session layer),表示层(Presentation layer),应用层(Application layer)
1.1 应用层,很简单,就是应用程序。这一层负责确定通信对象,并确保由足够的资源用于通信,这些当然都是想要通信的应用程序干的事情。 
1.2 表示层,负责数据的编码、转化,确保应用层的正常工作。这一层,是将我们看到的界面与二进制间互相转化的地方,就是我们的语言与机器语言间的转化。数据的压缩、解压,加密、解密都发生在这一层。这一层根据不同的应用目的将数据处理为不同的格式,表现出来就是我们看到的各种各样的文件扩展名。 
1.3 会话层,负责建立、维护、控制会话,区分不同的会话,以及提供单工(Simplex)、半双工(Half duplex)、全双工(Full duplex)三种通信模式的服务。我们平时所知的NFS,RPC,X Windows等都工作在这一层。 
1.4 传输层,负责分割、组合数据,实现端到端的逻辑连接。数据在上三层是整体的,到了这一层开始被分割,这一层分割后的数据被称为段(Segment)。三次握手(Three-way handshake),面向连接(Connection-Oriented)或非面向连接(Connectionless-Oriented)的服务,流控(Flow control)等都发生在这一层。 
1.5 网络层,负责管理网络地址,定位设备,决定路由。我们所熟知的IP地址和路由器就是工作在这一层。上层的数据段在这一层被分割,封装后叫做包(Packet),包有两种,一种叫做用户数据包(Data packets),是上层传下来的用户数据;另一种叫路由更新包(Route update packets),是直接由路由器发出来的,用来和其他路由器进行路由信息的交换。 
1.6 数据链路层,负责准备物理传输,CRC校验,错误通知,网络拓扑,流控等。我们所熟知的MAC地址和交换机都工作在这一层。上层传下来的包在这一层被分割封装后叫做帧(Frame)。 
1.7 物理层,就是实实在在的物理链路,负责将数据以比特流的方式发送、接收,就不多说了。 


3.2,TCP握手

3.2.1 三次握手建立连接

在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。
1,客户端向服务器发送一个SYN J
2,服务器向客户端响应一个SYN K,并对SYN J进行确认ACK J+1
3,客户端再想服务器发一个确认ACK K+1


从图中可以看出,当客户端调用connect时,触发了连接请求,向服务器发送了SYN J包,这时connect进入阻塞状态;服务器监听到连接请求,即收到SYN J包,调用accept函数接收请求向客户端发送SYN K ,ACK J+1,这时accept进入阻塞状态;客户端收到服务器的SYN K ,ACK J+1之后,这时connect返回,并对SYN K进行确认;服务器收到ACK K+1时,accept返回,至此三次握手完毕,连接建立。

三次握手的目的是建立双向的连接,第一次握手是客户端向服务器端发出请求 
第二次握手是服务器端告诉客户端,第一次握手是成功的,即可以从客户端发送到客户端, 
第三次握手是客户端告诉服务器端,第二次握手是成功的,即可以从客户端到服务器端 
这样就保证了客户端和服务器端的双向通信,

3.2.2 四次握手释放连接


1,某个应用进程首先调用close主动关闭连接,这时TCP发送一个FIN M;
2,另一端接收到FIN M之后,执行被动关闭,对这个FIN进行确认。它的接收也作为文件结束符传递给应用进程,因为FIN的接收意味着应用进程在相应的连接上再也接收不到额外数据;
3,一段时间之后,接收到文件结束符的应用进程调用close关闭它的socket。这导致它的TCP也发送一个FIN N;
4,接收到这个FIN的源发送端TCP对它进行确认。

3.3,socket编程

http://www.cnblogs.com/goodcandle/archive/2005/12/10/socket.html

先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。

3.3.1 AF_INET TCP传输最简单版本


tcp_client.c

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define PORT 6666
#define BUFF_SIZE 1024
#define MAXLEN 4096

main(int argc, char** argv)
{
    if(argc!=2){
        printf("usage: ./client <ipaddress>\n");
        exit(0);
    }
    
    char sendline[4096];
    
    //socket()建立socket
    int sockfd = socket(AF_INET,SOCK_STREAM,0);

	//要连接的服务器地址
    struct sockaddr_in sliaddr;
    sliaddr.sin_family = AF_INET;
    sliaddr.sin_port = htons(PORT);
    inet_pton(AF_INET, argv[1], &sliaddr.sin_addr);

    //connect()发送请求(ip=argv[1],protocal=TCP,port=6666)
    connect(sockfd, (struct sockaddr*)&sliaddr, sizeof(sliaddr));

	//recv sth
    recv_len = recv(sockfd, buff, sizeof(buff), 0);
    buff[recv_len] = '\0';
    printf(" %s ", buff);
 
    //interactive
    while (1)
    {
        printf("Enter string to send: ");
        scanf("%s", buff);
        if (!strcmp(buff, "quit"))
            break;
         
        send_len = send(sockfd, buff, strlen(buff), 0);
        recv_len = recv(sockfd, buff, BUFF_SIZE, 0);
        buff[recv_len] = '\0';
        printf("    received: %s \n", buff);
    }

    //close()关闭连接
    close(sockfd);
}

tcp_server.c

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define PORT 6666
#define WAIT_QUEUE_LEN 5
#define BUFF_SIZE 1024
#define WELCOME "Welcome to my server ^_^!\n"

main()
{
    int connfd;
    char buff[MAXLEN];
    int len;

    //socket() 建立socket,其中SOCK_STREAM表示tcp连接
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    
    struct sockaddr_in servaddr;
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(PORT);
    
    //bind()绑定一个socket(ip=all,protocal=TCP,port=6666)
    bind(sockfd,(struct sockaddr *) &servaddr, sizeof(servaddr));

    //listen()监听
    listen(sockfd, WAIT_QUEUE_LEN);

    //accept() & close()
    printf("======waiting for client's request======\n");
    while(1){
		c_addrlen = sizeof(struct sockaddr_in);
		connfd = accept(serverfd, (struct sockaddr *)&caddr, &c_addrlen);
        printf("client: ip=%s,port=%s\n", cliaddr.sin_addr.s_addr,cliaddr.sin_port);
		
		//send a welcome
		send(connfd, WELCOME, strlen(WELCOME), 0);
     
		//阻塞模式下recv==0表示客户端已断开连接
		while ((len = recv(connfd, buff, BUFF_SIZE, 0)) > 0)
		{
			buff[len] = '\0';
			printf("recv msg is : %s \n", buff);
			send(connfd, buff, len, 0);
		}
		
        close(connfd);
    }

    //close()关闭连接
    close(sockfd);
}
阻塞与非阻塞recv返回值没有区分,都是
<0 出错
=0 连接关闭
>0 接收到数据大小,

makefile

.PHONY : main
main : server client
server : server.o
        gcc -g -o server server.o 
client : client.o
        gcc -g -o client client.o 
server.o : server.c
        gcc -g -c server.c
client.o : client.c
        gcc -g -c client.c
clean : 
        rm -rf *.o
ser :
        ./server
cli :
        ./client
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
linux C语言 网络编程教程及源码 一、网络应用层编程 1、Linux网络编程01——网络协议入门 2、Linux网络编程02——无连接和面向连接的区别 3、Linux网络编程03——字节序和地址转换 4、Linux网络编程04——套接字 5、Linux网络编程05——C/S与B/S架构的区别 6、Linux网络编程06——UDP协议编程 7、Linux网络编程07——广播 8、Linux网络编程08——多播 9、Linux网络编程09——TCP编程之客户端 10、Linux网络编程10——TCP编程之服务器 11、Linux网络编程11——tcp、udp迭代服务器 12、Linux网络编程12——tcp三次握手、四次挥手 13、Linux网络编程13——connect()、listen()和accept()三者之间的关系 14、Linux网络编程14——I/O复用之select详解 15、Linux网络编程15——I/O复用之poll详解 16、Linux网络编程16——I/O复用之epoll详解 17、Linux网络编程17——tcp并发服务器(多进程) 18、Linux网络编程18——tcp并发服务器(多线程) 19、Linux网络编程——tcp高效并发服务器(select实现) 20、Linux网络编程——tcp高效并发服务器(poll实现) 21、Linux网络编程——tcp高效并发服务器(epoll实现) 二、网络底层编程(黑客模式) 1、Linux网络编程1——啥叫原始套接字 2、Linux网络编程2——原始套接字编程 3、Linux网络编程3——原始套接字实例:MAC头分析 4、Linux网络编程4——原始套接字实例:MAC地址扫描器 5、Linux网络编程5——IP数据报格式详解 6、Linux网络编程6——TCP、UDP数据包格式详解 7、Linux网络编程7——原始套接字实例:发送UDP数据包 8、Linux网络编程8——libpcap详解 9、Linux网络编程9——libnet详解

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值