Linux网络编程(一)socket模型创建

xiaoxiao2021-02-28  124

Socket、本身有“插座”的意思,在Linux环境下,用于表示进程间的网络通信的特殊文件类型,本质为内核借助缓冲区形成的伪文件。

既然是文件,我们就可以使用文件描述符引用套接字,与管道类似,Linux系统将其封装成文件的目的是为了统一接口,使得读写套接字和读写文件的操作保持一致,不过与管道还是有区别的,管道主要应用于本地进程间的通信,而套接字多应用于网络进程间的数据传输。

在TCP/IP协议层中,我们把“IP地址+TCP或UDP端口号”标识的网络中的唯一进程叫做Socket,那么两个网络进程之间数据的传输,就必须建立联系。 在网络通信中,套接字一定是成对出现的,一端的发送缓冲区对应另一端的接收缓冲区。我们使用同一个文件描述符发送缓冲区

网络应用程序设计模式: C/S模式: 传统的网络应用设计模式,客户机(client)与服务器(server)模式,需要在通信两端各自部署客户机与服务器来完成数据通信 B/S模式: 浏览器与服务器模式,只需要在一端部署服务器,而另一端使用默认配置的浏览器就可以完成数据传输。 优缺点: 对于C/S模型 优点:客户端位于目标主机可以保证性能,将数据缓存到客户端本地,从而提高数据传输效率,一般来说,客户端和服务器由开发团队创作,他们之间采用的协议可以灵活控制,因此,传统网络应用程序和较大的网络应用都是采用这种模型进行开发,网络游戏,3d画面等。 缺点:由于所有的事都是自己干,所以工作量倍增,开发周期变长,还有,客户端都是安装在用户主机上的,对用户主机也会造成一定的威胁。 对于B/S模型: 由于没有独立的客户端,使用标准浏览器作为客户端,其工作量小,开发周期短,采用浏览器显示数据,可移植性高,不受平台限制,例如网页游戏,请求偷菜等。 缺点: 由于采用第三方浏览器,所以数据的缓存能力受到限制,而且之间必须与浏览器一样使用标准的通信协议(HTTP协议)

网络编程知识:

网络字节序: 网络字节序通俗一点就是在传递数据过程中所遵循的一种网络数据流。 一般我们的主机在内存中的存储方式是有所不同的,有的主机是大端存储(高位放在低地址),有的主机是小端存储(低地址放在低位上),所以在网络上传递数据报时,就可能出现不可预期的差错,为了防止这种情况,我们的TCP/IP协议组规定,网络传输必须采用大端的存储方式,这就要求不管是客户端还是服务端,在发送数据与接收数据之前,要做网络字节序与主机字节序的转换。 Socket模型创建 ![这里写图片描述](https://imgconvert.csdnimg.cn/aHR0cDovL2ltZy5ibG9nLmNzZG4ubmV0LzIwMTcwODA2MTIzOTAzMjY0?x-oss-process=image/format,png) 服务器端: ```

//创建监听套接字 #include <sys/types.h> #include <sys/socket.h>

int socket(int domain, int type, int protocol);

// int listen_fd; // listen_fd = socket(AF_INET,SOCK_STREAM,0); //SOCK_STREAM(面向字节流,可靠的,按顺序的连接,基于TCP) //SOCK_DGRAM(无连接的,固定数据长度的传输调用,不可靠的,基于UDP传输)

//设置结构体,转换端口与ip

struct sockaddr_in local; local.sin_family = AF_INET; local.sin_port = htons(atoi(argv[2])); //端口 local.sin_addr.s_addr = inet_addr(argv[1]); //IP

//绑定,监听套结字与自己服务器ip绑定

int bind(int sockfd, const struct sockaddr addr, socklen_t addrlen); //bind(listen_fd,(struct sockaddr_in)&local,sizeof(local) )

//设置监听模式,创建队列,把用户信息填充到队列 int listen (int sockfd, int backlog) // listen (listen_fd,10);

//拿到监听者信息,建立链接,返回rw_sockfd struct sockaddr_in client_addr; int* rw_sockfd = NULL; while(1) { rw_sockfd =accept(listen_fd,(struct sockaddr_in*)&client_addr,sizeof(client_addr));

write(); read(); close(rw_sockfd) } //这是一个死循环过程,每次循环处理一个客户端连接,服务器与客户端数据传输都是通过accept()新得到的rw_sockfd来完成的,当数据传输结束,关闭rw_sockfd,而不关闭listenfd,再次循环进行下一轮监听

<table><tr><td bgcolor=#7FFFD4>客户端: </td></tr></table>

//创建套接字 int socket(int domain, int type, int protocol);

// int sockfd; // sockfd = socket(AF_INET,SOCK_STREAM,0);

//设置结构体状态,拿到服务器端ip与port struct sockaddr_in local; local.sin_family = AF_INET; local.sin_port = htons(atoi(argv[2]));//port端口 local.sin_addr.s_addr = inet_addr(argv[1]);//本地ip

//向服务器发起连接请求 int connect(int sockfd,const struct sockaddr* addr,socklen_t addrlen)

// connect(sockfd,(struct sockaddr_in*)&local,sizeof(local)))

转载请注明原文地址: https://www.6miu.com/read-49311.html

最新回复(0)