Socket编程

一.Socket编程基础知识

1.什么是Socket编程

Socket编程是独立于具体协议的网络编程接口。
在ISO模型中,主要位于会话层和传输层之间。
BSD Socket(伯克利套接字)是通过标准的UNIX文件描述符和其它程序通讯的一个方法,目前已经被广泛移植到各个平台。

2.为什么需要Socket

普通的I/O操作过程:
打开文件 -> 读/写操作 -> 关闭文件
TCP/IP协议被集成到操作系统的内核中,引入了新型的“I/O”操作:
不同的机器上的两个进程进行网络操作,如何连接?
网络协议具有多样性,如何进行统一的操作?
这就需要一种通用的网络编程接口:Socket

3.Socket类型

流式套接字(SOCK_STREAM):
提供了一个面向连接、可靠的数据传输服务,数据无差错、无重复的发送且按发送顺序接收。
数据报套接字(SOCK_DGRAM):
提供无连接服务。数据包以独立数据包的形式被发送,不提供无差错保证,数据可能丢失,重复或失序。
原始套接字(SOCK_RAW):
可以对较低层次协议,如IP、ICMP直接访问。

4.Linux Socket

基本上就是BSD Socket
需要使用的头文件:
数据类型:#include <sys/types.h>
函数定义:#include <sys/socket.h>

二.Socket基本函数-常用函数

网络连接函数

1.创建套接字socket()函数

应用程序在使用套接字通信前,必须要拥有一个套接字,使用socket()函数来给应用程序创建一个套接
字。

SOCKET socket(
    int af,
    int type,
    int protocol
);

af参数说明套接字接口要使用的协议地址族,地址族与协议族含义相同。如果想建立一个TCP或UDP,只能用常量AF_INET表示使用互联网协议(IP)地址。Winsock还支持其他协议,但一般很少使用。

type参数描述套接字的类型,af是AF_INET的时候只能为SOCK_STREAM、SOCK_DGRAM或SOCK_RAW。

protocol参数说明该套接字使用的特定协议,当协议地址族af和协议类型type确定后,协议字段可以使用的值是限定的。

2.指定本地地址-bind()函数

当socket()创建了一个套接字后,需要将该套接字与该主机上提供服务的某端口联系在一起,bind()函数
用于完成这样的绑定。

int bind(
    SOCKET s,
    const struct sockaddr FAR * name,
    int namelen
);

s参数 标识一个未绑定的套接字描述字,它是socket()函数调用成功时返回的值。

name参数是一个与指定协议有关的地址结构指针,存储了套接字的地址信息。

namelen参数表示地址参数(name)的长度。

3.服务器端启动监听-listen()函数

在一个服务器端用socket()调用成功创建了一个套接字,并用bind()函数和一个指定的地址关联后,就需要指示该套接字进入监听连接请求状态,这需要通过listen()函数来实现

int listen(
    SOCKET s,
    int backlog
);

s参数代表一个已绑定了地址,但还未建立连接的套接字描述字。

backlog参数指定了正在等待连接的最大队列长度。

4.客户端请求连接-connect()函数

当服务器端建立好套接字并与一个本地地址绑定后,就进入监听状态,等待客户发出连接请求。在客户端套接字建立好之后,就调用connect()函数来与服务器建立连接。

int connect(
   SOCKET s,
   const struct sockaddr FAR * name,
   int namelen
);

s参数将要建立连接的套接字描述字。

name参数是一个指向远端套接字地址结构(sockaddr_in)的指针,表示s套接字欲与其建立一条连接。

namelen参数是服务器端的地址长度,即name的长度。

在客户端使用该函数请求建立连接时,将激活建立连接的三次握手,用来建立一条到服务器TCP的连接。如果调用该函数前没有调用bind()来绑定本地地址,则由系统隐式绑定一个地址到该套接字。

5.服务器端接受连接-accept()函数

在服务器端通过listen()函数调用表示服务器进入监听客户的连接请求状态,而在服务器端调用accept()函数时表示可以接收来自客户端由connect()发出的连接请求,双方进入连接状态。

SOCKET accept(
SOCKET s,
struct sockaddr FAR * addr,
int FAR * addrlen
);

s参数标识一个套接字,该套接字处于监听状态。
addr参数是一个地址结构的指针,用来存放发出连接请求的那个客户机的IP地址信息
addrlen参数指出客户套接字地址结构的长度。

该函数从s的等待连接队列中抽取第一个连接,创建一个与s同类的新的套接字并返回句柄。
该函数用于面向连接的服务器端,在IP协议族中,只用于TCP服务器端。

6.发送数据-send()函数

在已经建立连接的套接字上发送数据,可以使用send()函数

int send(
    SOCKET s,
    const char FAR * buf,
    int len,
    int flags
);

s参数用于标识已建立连接的套接字。
buf参数是一个字符缓冲区,内有将要发送的数据。
len参数即将发送的缓冲区中的字符数。
flags参数用于控制数据传输方式,0表示按正常方式。发送数据;宏MSG_DONTROUTE说明系统目
标主机就在直接连接的本地网络中,无需路由选择;MSG_OOB指出数据是按带外数据发送的。

7.接收数据-recv()函数

对于已建立连接的套接字来说,要从套接字上接收数据,就要使用recv()函数。

int recv(
    SOCKET s,
    char FAR * buf,
    int len,
    int flags
);

s参数为已建立连接的套接字。
buf参数为用于接收数据的缓冲区。
len参数为缓冲区的长度。
flags参数指定调用的方式。0表示接收的是正常数据,无特殊行为。MSG_PEEK表示会使有用的数据复制到所提供的接收端缓冲区内,但是没有从系统缓冲区中将数据删除。MSG_OOB表示处理带外数据。

8.无连接的套接字上接收数据-recvfrom()函数

对于无连接的套接字来说,要从套接字上接收一个数据报并保存发送数据的源地址,就要使用recvfrom()函数。

int recvfrom(
    SOCKET s,
    char FAR * buf,
    int len,
    int flags,
    struct sockaddr FAR * from,
    int FAR * fromlen
);

s参数标识一个套接字的描述字。
buf参数接收数据的缓冲区。
len参数接收数据缓冲区的长度。
flags参数调用操作方式,同recv()中的flags。
from参数可选指针,指向装有源地址的缓冲区。
fromlen参数可选指针,指向from缓冲区的长度值。
该函数的用法与有连接时recv()的用法一致,要注意的是该函数也可以用于有连接时数据的接收。

9.在无连接套接字上发送数据-sendto()

对于无连接的套接字来说,要从套接字上发送一个数据报,就要使用sendto()函数

int sendto(
    SOCKET s,
    const char FAR * buf,
    int len,
    int flags,
    const struct sockaddr FAR * to,
    int tolen
);

s参数本机的套接字。
buf参数待发送数据的缓冲区。
len参数指明buf缓冲区中要发送的数据长度。
flags参数调用方式标志位,同send()中的flags。
to参数可选指针,指向接收数据的目的套接字地址。
tolen参数是to所指的地址的长度。
该函数的使用方法类似send()函数,当用于无连接套接字接口,调用函数前要设置,指出目标IP地址和目标端口号。如果用于有连接的套接字时,则不能指定目标地址和目标端口,将to设置为空,地址长度设为0。当然在有连接的情况下很少使用该函数。

10.关闭读写通道-shutdown()函数

在一个套接字上的读写操作完成后,应该首先使用shutdown()函数来关闭套接字的读通道、写通道或读写通道,这样做的好处是当双方不再有数据要发送或接收时,可以通知对方,以防止数据丢失,并能“优雅”地关闭连接。

int shutdown(
    SOCKET s,
    int how
);

s参数标识一个套接字的描述字。
how参数是一个标志,用于描述禁止哪些操作。

11.关闭套接字-closesocket()函数

shutdown函数只关闭读写通道,并不关闭套接字,且套接字所占有的资源将被一直保留到closesocket()调用之前。
一个套接字不再使用时一定要关闭这个套接字,以释放与该套接字关联的所有资源,包括等候处理的数据。

int closesocket(
SOCKET s
);

参数s表示即将被关闭的套接字。

12.IP地址转换函数

char * inet_ntoa ( struct in_addr in )
in为传入参数,表示一个结构型的IP主机地址,该函数将一个32位数字表示的IP地址转换成点分十进制IP地址字符串。
unsigned long inet_addr(const char FAR * cp)
该函数将一个点分十进制IP地址字符串转换成32位数字表示的IP地址。

两函数互为反函数。

13.字节序转换函数

u_long htonl( u_long hostlong )
4字节主机字节序表示的整数转换为4字节相应的网络字节序表示的整数
u_short htons( u_short hostshort )
2字节主机字节序表示的整数转换为2字节相应的网络字节序表示的整数
u_long ntohl( u_long netlong )
4字节网络字节序表示的整数转换为4字节相应的主机字节序表示的整数
u_short ntohs( u_short netshort )
2字节网络字节序表示的整数转换为2字节相应的主机字节序表示的整数

14.Winsock-WSACleanup()函数

当应用程序不再使用Winsock API中的任何函数时,必须调用WSACleanup()将其从Windows Socket的实
现中注销,以释放为此应用程序或DLL分配的任何资源。

WSACleanup(void)

WSACleanup()函数是任何一个Winsock应用程序在最后必须要调用的函数。在一个多线程的环
境下,WSACleanup()函数中止了Windows Sockets在所有线程上的操作。

三.Socket常用函数-网络信息检索函数

网络信息检索函数:
gethostname 获得主机名
getpeername 获得与套接字相连的远程协议地址
getsockname 获得套接字本地协议地址
gethostbyname 根据主机名取得主机信息
gethostbyaddr 根据主机地址取得主机信息
getprotobyname 根据协议名取得主机协议信息
getprotobynumber 根据协议号取得主机协议信息
getservbyname 根据服务名取得相关服务信息
getservbyport 根据端口号取得相关服务信息
getsockopt/setsockopt 获取/设置一个套接字选项
ioctlsocket 设置套接字的工作方式

四.

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值