网络编程就是编写程序使两台连网的计算机相互交换数据。
套接字时网络数据传输用的软件设备。
首先构建接电话套接字
调用socket函数(安装电话机)
#include<sys/socket.h>
int socket(int domain, int type, int protocol); //成功时返回文件描述符,失败时返回-1
调用bind函数(分配电话号码)
int bind(int sockfd, struct sockaddr *myaddr, socklen_t addrlen); //成功时返回0,失败时返回-1
调用listen函数(连接电话线)
int listen(int sockfd, int backlog); //成功时返回0,失败时返回-1
调用accept函数(拿起话筒)
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); //成功时返回文件描述符,失败时返回-1
网络编程中接受连接请求的套接字创建过程整理如下:
注意:Linux系统下不区分套接字和文件
在这里我们经常看到ssize_t、size_t这种数据类型(size_t是通过typedef声明的unsigned int类型,对于ssize_t来说,前面的s代表signed,所以,ssize_t代表signed int
),这些属于元数据类型,在sys/types.h头文件中一般由typedef声明定义,算是给大家熟悉的基本数据类型起了别名。那么为什么要这样做呢?
因为随着时代的变化,系统的不同,数据类型的表现也不一样。以前的操作系统int是16位的,现在大多是32位的。所以在不同的操作系统上,只需修改size_t和ssize_t的typedef声明即可。为了与程序员定义的新数据类型加以区分,操作系统定义的数据类型会添加后缀_t。
Windows下网络编程
为windows套接字编程设置头文件和库
为了在Winsock基础上开发网络程序,需要做如下准备。
对于上面两个参数的详细说明以下。第一个,Winsock中存在多个版本,应准备WORD类型(WORD是通过typedef定义的unsigned short类型)套接字版本信息,传递给该函数的第一个参数。若版本为1.2,其中1是主版本号,2是副版本号,应传递0x0201。高八位为副版本号,低八位为主版本号。可以通过MAKEWORD宏函数构建版本信息。
MAKEWORD(1, 2); // return 0x0201
第二个,lpWSADATA,此参数需传入WSADATA型结构体变量地址(lpWSADATA是WSADATA的指针类型),调用完函数后,相应参数中将填充已初始化的库信息。
那么如何注销该库
int WSACleanup(void);//成功返回0,失败时返回SOCKET_ERROR
调用该函数时Winsock相关库将归还Windows操作系统,无法再调用Winsock相关函数。无需调用Winsock函数时才调用该函数,通常在程序结束之前调用。
基于Windows的套接字相关函数
#include<winsock2.h>
SOCKET socket(int af, int type, int protocol); //成功返回套接字句柄,失败时返回INVALID_SOCKET
bind函数分配IP地址和端口号
int bind(SOCKET s, const struct sockaddr *name, int namelen); //成功返回0,失败时返回SOCKET_ERROR
listen函数调用套接字可接收客户端连接
int listen(SOCKET s, int backlog); //成功返回0,失败时返回SOCKET_ERROR
accept调用受理客户端连接请求
SOCKET accept(SOCKET s,struct sockaddr *addr, int *addrlen); //成功返回套接字句柄,失败时返回INVALID_SOCKET
从客户端发送连接请求
int connect(SOCKET s, const struct sockaddr *name, int namelen); //成功返回0,失败时返回SOCKET_ERROR
关闭套接字时使用,windows区分套接字和文件,,所以有专门关闭套接字的函数
int closesocket(SOCKET s); //成功返回0,失败时返回SOCKET_ERROR
要注意在windows下,文件句柄相关函数和套接字句柄相关函数是有区别的。
Winsock数据传输函数
int send(SOCKET s, const char *buf, int len, int flags); //成功时返回传输字节数,失败时返回SOCKET_ERROR
int recv(SOCKET s, const char *buf, int len, int flags); //成功时返回传输字节数,失败时返回SOCKET_ERROR