计算机网络学习笔记(二)- Socket编程

Socket API概述

  1. 标识通信端点(对外):IP地址+端口号
  2. 操作系统/进程如何管理套接字(对内):套接字描述符(创建了一个套接字,怎么找到并调用它,内部通过套接字描述符,外部通过IP地址+端口号,也就是通过IP地址和端口号即可定位外部的一个套接字)

Socket抽象

  • 类似于文件的抽象
  • 当应用进程创建套接字时,操作系统分配一个数据结构存储该套接字相关信息,返回套接字描述符
  • 地址结构
	struct sockaddr_in
	{
   
		u_char sin_len; 			/*地址长度 */
		u_char sin_family; 			/*地址族(TCP/IP:AF_INET) */
		u_short sin_port; 			/*端口号 */
		struct in_addr sin_addr; 	/*IP地址 */
		char sin_zero[8]; 			/*未用(置0) */
	}

Socket API函数

WSAStartup函数

  1. 使用Socket的应用程序在使用Socket之前必须首先调用WSAStartup函数
  2. 两个参数:
    • 第一个参数指明程序请求使用的WinSock版本,其中高位字节指明副版本、低位字节指明主版本,十六进制整数,例如0x102表示2.1版
    • 第二个参数返回实际的WinSock的版本信息,指向WSADATA结构的指针
	// 函数调用格式
	int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);
	// 调用示例(使用2.1版本的WinSock的程序代码段)
	wVersionRequested = MAKEWORD( 2, 1 ); 
	err = WSAStartup( wVersionRequested, &wsaData );

WSACleanup函数

  1. 应用程序在完成对请求的Socket库的使用, 最后要调用WSACleanup函数
  2. 解除与Socket库的绑定
  3. 释放Socket库所占用的系统资源
	// 调用格式
	int WSACleanup (void);

Socket函数

  1. 创建套接字
  2. 操作系统返回套接字描述符(sd)
  3. 第一个参数(协议族): protofamily = PF_INET(TCP/IP)
  4. 第二个参数(套接字类型):
    如下图所示,type参数有三种选择,SOCK_STREAM对应TCP类型,SOCKET_DGRAM对应UDP类型,SOCK_RAW直接对应网络层,当使用此方式时要求权限非常高,如果是Linux系统,则要求有root权限
  1. 第三个参数(协议号):0为默认
	// 调用格式
	sd = socket(protofamily, type, proto);
	// 调用示例
	struct protoent *p;
	p = getprotobyname("tcp");
	SOCKET sd = socket(PF_INET, SOCK_STREAM, p->p_proto);

Closesocket函数

  1. 关闭一个描述符为sd的套接字
  2. 如果多个进程共享一个套接字,调用closesocket将套接字引用计数减1,减至0才关闭
  3. 一个进程中的多线程对一个套接字的使用无计数
  4. 如果进程中的一个线程调用closesocket将一个套接字关闭,该进程中的其他线程也将不能访问该套接字
  5. 返回值:
    • 0:成功
    • SOCKET_ERROR:失败
	// 调用格式
	int closesocket(SOCKET sd);

bind函数

  1. 绑定套接字的本地端点地址:IP地址+端口号
  2. 参数:
    • 套接字描述符(sd)
    • 端点地址(localaddr):结构sockaddr_in
    • 地址结构的长度
  3. 客户程序一般不必调用bind函数
  4. 当遇见如下图所示情形,即一个主机/服务器连接了两个网络,也就有了两个IP地址,此时采用地址通配符的方式,地址通配符:INADDR_ANY
	int bind(sd, localaddr, addrlen);

listen函数

  1. 置服务器端的流套接字处于监听状态(监听状态是指网络服务端程序所处的一种状态,在该状态下,服务端程序等待客户端的请求)
    仅服务器端调用
    仅用于面向连接的流套接字
  2. 设置连接请求队列大小(queuesize)(客户端请求队列,当有来自客户端的请求时,放入队列,但不响应请求,响应请求时另一个函数)
  3. 返回值:
    • 0:成功
    • SOCKET_ERROR:失败
	// 调用格式
	int listen(sd, queuesize);

connect函数

  1. 客户程序调用connect函数来使客户套接字(sd)与特定计算机的特定端口(saddr)的套接字(服务)进行连接(用于TCP建立连接)
  2. 用于客户端
  3. 可用于TCP客户端也可以用于UDP客户端
    • TCP客户端:建立TCP连接
    • UDP客户端:指定服务器端点地址(UDP是一种无连接的方式,所以这个函数并不能有效建立UDP的连接)

accept函数

  1. 服务程序调用accept函数从处于监听状态的流套接字sd的客户连接请求队列中取出排在最前的一个客户请求,并且创建一个新的套接字来与客户套接字创建连接通道
    仅用于TCP套接字
    仅用于服务器
  2. 利用新创建的套接字(newsock)与客户通信
	// 调用格式
	newsock = accept(sd, caddr, caddrlen);

send, sendto函数

  1. send函数用于TCP套接字(客户与服务器)或调用了connect函数的UDP客户端套接字(send函数用于发送数据,但函数并未指定发送的端口地址,这是因为TCP已经建立了连接,不需要指定,而调用了connect函数的UDP客户端,由于指定了端口,所以函数也不需要指定发送端口)
  2. sendto函数用于UDP服务器端套接字与未调用connect函数的UDP客户端套接字
	// 调用格式
	send(sd,*buf,len,flags);
	sendto(sd,*buf,len,flags,destaddr,addrlen);

recv, recvfrom函数

  1. recv函数从TCP连接的另一端接收数据,或者从调用了connect函数的UDP客户端套接字接收服务器发来的数据(receive函数用于接受数据,但函数并未指定发送的端口地址,这是因为TCP已经建立了连接,不需要指定,而调用了connect函数的UDP客户端,由于指定了端口,所以函数也不需要指定发送端口)
  2. recvfrom函数用于从UDP服务器端套接字与未调用connect函数的UDP客户端套接字接收对端数据
	// 调用格式
	recv(sd,*buffer,len,flags);
	recvfrom(sd,*buf,len,flags,senderaddr
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值