第1章 网络编程和套接字
1.1网络编程和套接字概览
C++
#include <sys/socket.h>
//创建套接字,成功时返回文件描述符,失败返回-1
int socket(int domain,int type,int protocol);
//给创建好的套接字分配地址信息(IP地址和端口号)成功返回0,失败返回-1
int bind(int sockfd,struct sockaddr *myaddr,socklen_t addrlen);
//将套接字转换成可接受的状态 成功返回0,失败返回-1
int listen(int sockfd,int backlog);
//接受请求 成功时返回文件描述符,失败返回-1
int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);
网络编程中中接受连接请求的套接字创建过程整理如下:
- 调用socket函数创建套接字
- 调用bind函数分配IP地址和端口号
- 调用listen函数转为可接收请求状态
- 调用accept函数受理连接请求
构建服务器端实例
客服端程序只有调用socket函数创建套接字和调用connect函数向服务器端发送连接请求两个步骤。
C++
#include <sys/socket.h>
//成功返回0,失败返回-1
int connect(int sockfd,struct sockaddr *serv_addr,socklen_t addrlen);
客户端程序
以上是Linux环境中编译并执行的程序。
Bash
gcc hello_server.c -o hserver
./hserver
gcc hello_client.c -o hclient
./hclient 127.0.0.1 9190
1.2基于Linux文件操作
系统分配给文件或者套接字的整数称为文件描述符。文件描述符只不过是为了方便称呼操作系统创建的文件或套接字而赋予的数而已。文件描述符在windows中被称为句柄,Linux平台则用“描述符”。
C++
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
//成功时返回文件描述符,失败时返回-1
//第一个参数打开文件名以及路径信息,第二个参数 文件打开的模式(文件特性信息)
int open(const char *path, int flag);
//关闭文件,不管可以关闭文件,还可以关闭套接字
//成功时返回0,失败时返回-1
int close(int fd);
第二个参数可能的常量值以及含义。如果需要传递多个参数,则通过位或运算(OR)符组合传递。
C++
#include <unistd.h>
//将数据写入文件
//fd 显示数据传输对象的文件描述符
//buf 保存要传输数据的缓冲地址值
//nbytes 要传输数据的字节数
//size_t是通过typedef声明的unsigned int类型 ,sszie_t第一个s代表signed
ssize_t write(int fd,const void * buf,size_t nbytes);
//fd 显示数据传输对象的文件描述符
//buf 保存要传输数据的缓冲地址值
//nbytes 要接收的最大字节数
ssize_t read(int fd,void * buf,size_t nbytes);
文件描述符和套接字
同时创建文件和套接字,并用整数形态比较返回的文件描述符值。
从输出的文件描述符整数值可以看出,描述符从3开始以由小到大的顺序编号,因为0、1、2是分配给标准I/0的描述符。
1.3基于windows平台实现
windows套接字(Winsock),需要导入头文件winsock2.h,链接ws2_32.lib库。
C++
#include <winsock2.h>
//初始化方法
//wVersionRequested winsock的版本信息 lpWSAData WSADATA结构体变量的地址值
int WSAStartup(WORD wVersionRequested,LPWSADATA lpWSAData);
//注销方法 成功返回0 失败返回SOCKET_ERROR
int WSAClearnup(void);
1.4基于Windows的套接字相关函数以及示例
C++
#include <winsock2.h>
//成功时返回套接字句柄,失败时返回INVALID_SOCKET
SOCKET socket(int af,int type,int protocol);
//成功时返回0,失败时返回socket_error
int bind(SOCKET s,const struct sockaddr * name,int namelen);
//成功时返回0,失败时返回socket_error
int listen(SOCKET s,int backlog);
//成功时返回0,失败时返回INVALID_SOCKET
SOCKET accept(SOCKET s,struct sockaddr * addr,int * addrlen);
//成功时返回0,失败时返回socket_error
int connect(SOCKET s,const struct sockaddr * name,int namelen);
//成功时返回0,失败时返回socket_error
int closesocket(SOCKET s);
文件句柄相关函数与套接字句柄相关函数是有区别的,这一点不同于Linux文件描述符。
创建基于windows的服务器和客户端
客户端相关代码
基于Windows的I/O函数
C++
#include <winsock2.h>
//s 表示数据传输对象连接的套接字句柄值 buf保存待传输数据的缓冲地址值
//len 要传输的字节数 flags传输数据用到的多种选项信息
int send(SOCKET s,const char * buf,int len,int flags);
//s 表示数据传输对象连接的套接字句柄值 buf保存待传输数据的缓冲地址值
//len 要传输的字节数 flags传输数据用到的多种选项信息
int recv(SOCKET s,const char * buf,int len,int flags);