windows下的socket(1)

winsock的初始化

进行winsock编程时,首先必须调用WSAStartup函数,设置程序中用到的Winsock版本,并初始化相应版本的库。

#include<winsock2.h>

int WSASartup(WORD   wVersionRequested   ,   LPWSADATA   lpWSAData  );
//成功时返回0,失败时返回非零的错误代码值。

  wVersionRequested     程序员要用的Winsock版本信息。
  lpWSAData                   WSADATA结构体变量的地址值

有必要给出上述两个参数的详细说明。第一个,Winsock中存在多个版本,应准备WORD类型的(WORD是通过typedef声明定义的unsiged short类型)套接字版本信息,并传递给该函数的一个参数wVersionRequested。若版本为1.2,则其中1是主版本号,2是副版本号,应传递0x0201。
  借助MAKEWORD宏函数则能轻松构建WORD型版本信息。

MAKEWORD(1  ,  2);   //主版本为1,副版本为2,返回0x0201
MAKEWORD(2  ,  2);   //主版本为2,副版本为2,返回0x0202

winsock库注销

#include<winsock2.h>
int WSACleanup();
//成功时返回0,失败时返回SOCKET_ERROR.

调用该函数时,winsock相关库将归还windows操作系统,无法再调用winsock相关函数。从原则上讲,无需再使用winsock函数时才调用该函数,但通常都在程序结束之前调用。


socket函数

//成功时返回socket句柄,失败时返回INVALID_SOCKET。

SOCKET socket(int af , int  type , int  protocol);
   af                  套接字中使用的协议族信息
   type              套接字数据传输类型信息
   protocol        计算机间通信中使用的协议信息

协议族类型:
                 PF_INET                                 IPv4互联网协议族
                 PF_INET6                               IPv6互联网协议族
                 PF_LOCAL                             本地通信的unix协议族
                 PF_PACKET                           底层套接字的协议族
                 PF_IPX                                   IPX  Novell协议族
    

套接字类型(type):       
1.面向连接的套接字(SOCK_STREAM)   
特点:
1)传输过程中数据不会消失
2)按顺序传输数据
3)传输的数据不存在数据边界

2.面向消息的套接字(SOCK_DGRAM)
特点:
1)强调快速传输而非传输顺序
2)传输的数据可能丢失也可能损毁
3)传输的数据有数据边界
4)限制每次传输的数据大小

3协议信息(填写0 根据前面的两个参数,默认填写合适的协议)
1)TCP套接字
socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
2)UDP套接字
socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);

bind函数

//成功时返回0,失败时返回SOCKET_ERROR
int bind(Socket s,const struct sockaddr * name,int namelen);
         s                  套接字句柄
      name              存有地址信息的结构体变量地址值
      namelen         第二个结构体变量的长度

listen函数

//成功时返回0,失败时返回SOCKET_ERROR
int listen(SOCKET s,int backlog);

accept函数

//成功时返回套接字句柄,失败时返回INVALID_SOCKET。
SOCKET accept(SOCKET s,struct sockaddr* addr,int * addrlen);

connect函数

//成功时返回0,失败时返回SOCKET_ERROR
int connect(SOCKET s,const struct sockaddr* name,int namelen);

cloessocket函数

//成功时返回0,失败时返回SOCKET_ERROR
int closesocket(SOCKET S);

传输函数

//成功时返回传输字节数,失败时返回SOCKET_ERROR
int send(SOCKET s, const char*buf , int len , int flags );
     s          表示数据传输对象连接的套接字句柄值
    buf        保存带传输数据的缓冲地址值
     len       要传输的字节数
    flags     传输数据时用到的多种选项信息

//成功时返回传输字节数(收到EOF时为0),失败时返回 SOCKET_ERROR
int recv(SOCKET s, const char*buf , int len , int flags );
     s          表示数据传输对象连接的套接字句柄值
    buf        保存带传输数据的缓冲地址值
     len       要传输的字节数
    flags     传输数据时用到的多种选项信息

服务器:

//服务器代码

#include<stdlib.h>
#include<stdio.h>
#include<WinSock2.h>
#pragma comment(lib,"ws2_32.lib") //显示调用ws2_32.lib

void ErrorHanding(char* message);
int main() {
	WSADATA wsadata;
	SOCKET hserverSocket, hclientSocket;
	SOCKADDR_IN serveraddr, clientaddr;
	int szClientAdd;
	char message[] = "这是服务器!";
	
	if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0) //初始化winsock库
		ErrorHanding("WSAStartup() error");
	hserverSocket = socket(PF_INET, SOCK_STREAM, 0); // IPV4 面向连接传输
	if (hserverSocket == INVALID_SOCKET)
		ErrorHanding("socket() error");

	memset(&serveraddr, 0, sizeof(serveraddr));//清空,值全为0

	serveraddr.sin_family = AF_INET;    //IPv4
	serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);  //自动寻找本机地址
	serveraddr.sin_port = htons(6666);  //端口为 6666
	
	//绑定服务器地址
	if (bind(hserverSocket, (SOCKADDR*)&serveraddr, sizeof(serveraddr)) == SOCKET_ERROR)
		ErrorHanding("bind() error");
	//使套接字成为服务器套接字
	if (listen(hserverSocket,5) == SOCKET_ERROR) {
		ErrorHanding("listen() error");
	}
	szClientAdd = sizeof(clientaddr);
	hclientSocket = accept(hserverSocket, (SOCKADDR*)&clientaddr, &szClientAdd);
	if (hclientSocket == INVALID_SOCKET)
		ErrorHanding("accept() Error");

	send(hclientSocket, message, sizeof(message),0);

	closesocket(hclientSocket);  //关闭客户套接字
	closesocket(hserverSocket);  //关闭服务器套接字
	WSACleanup();  //清理winsock库
	return 0;
}
void ErrorHanding(char* message) {
	fputs(message, stderr);
	fputc('\n', stderr);
}
客户端代码:

#include<stdlib.h>
#include<stdio.h>
#include<WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
void ErrorHanding(char* message);
int main() {
	WSADATA wsadata;
	SOCKET hclientsocket;
	SOCKADDR_IN servAddr;

	char message[30];
	int strlen;

	if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0)
		ErrorHanding("WSAStartup() error");
	hclientsocket = socket(PF_INET, SOCK_STREAM, 0);
	if (hclientsocket == INVALID_SOCKET)
		ErrorHanding("socket() error");

	memset(&servAddr, 0, sizeof(servAddr));
	servAddr.sin_family = AF_INET;
	servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");  //回送地址,访问本地
	servAddr.sin_port = htons(6666); //端口号
	//客户端套接字通过目的地址建立连接
	if (connect(hclientsocket, (SOCKADDR*)&servAddr, sizeof(servAddr)))
		ErrorHanding("conect() error");
	//读取数据
	strlen = recv(hclientsocket, message, sizeof(message),0);
	if (strlen == -1) ErrorHanding(" read() error");

	printf("message from server:%s \n", message);
	getchar();
	closesocket(hclientsocket);
	WSACleanup();
	return 0;
}
void ErrorHanding(char* message) {
	fputs(message, stderr);
	fputc('\n', stderr);
}



Windows Sockets网络编程》是WindowsSockets网络编程领域公认的经典著作,由Windows Sockets2.0规范解释小组负责人亲自执笔,权威性毋庸置疑。它结合大量示例,对WindowsSockets规范进行了深刻地解读,系统讲解了WindowsSockets网络编程及其相关的概念、原理、主要命令、操作模式,以及开发技巧和可能的陷阱,从程序员的角度给出了大量的建议和最佳实践,是学习WindowsSockets网络编程不可多得的参考书。   全书分为三部分:第一部分(第1~6章),提供了翔实的背景知识和框架方面的概念,借助于此框架,读者可理解WinSock的具体细节,包括WindowsSockets概述、OSI网络参考模型、TCP/IP协议簇中的协议和可用的服务、WinSock网络应用程序的框架及其工作机制、WinSock的三种操作模式、socket通信机制等;第二部分(第7~12章),以FTP客户端实例为基础介绍了函数实例库,还介绍了客户端程序、服务器程序和DLL中间构件及它们的相应函数,并涵盖socket命令和选项及移植BSDSockets相关事项等;第三部分(第13~17章),介绍了应用程序调试技术和工具,针对应用编程中的陷阱的建议和措施,WinSockAPI的多种操作系统平台,WinSock规范的可选功能和WinSock规范2.0中的所有新功能。 译者序 序 前言 第1章 Windows Sockets概述 1.1 什么是Windows Sockets 1.2 Windows Sockets的发展历史 1.3 Windows Sockets的优势 1.3.1 Windows Sockets是一个开放的标准 1.3.2 Windows Sockets提供源代码可移植性 1.3.3 Windows Sockets支持动态链接 1.3.4 Windows Sockets的优点 1.4 Windows Sockets的前景 1.5 结论 第2章 Windows Sockets的概念 2.1 OSI网络模型 2.2 WinSock网络模型 2.2.1 信息与数据 2.2.2 应用协议 2.3 WinSock中的OSI层次 2.3.1 应用层 2.3.2 表示层 2.3.3 会话层 2.3.4 传输层 2.3.5 网络层 2.3.6 数据链路层 2.3.7 物理层 2.4 模块化的层次框 2.5 服务和协议 2.6 协议和API 第3章 TCP/IP协议服务 3.1 什么是TCP/IP 3.2 TCP/IP的发展历史 3.3 传输服务 3.3.1 无连接的服务:UDP 3.3.2 面向连接的服务:TCP 3.3.3 传输协议的选择:UDP与TCP的对比 3.4 网络服务 3.4.1 IP服务 3.4.2 ICMP服务 3.5 支持协议和服务 3.5.1 域名服务 3.5.2 地址解析协议 3.5.3 其他支持协议 3.6 TCP/IP的发展前景 第4章 网络应用程序工作机制 4.1 客户端-服务器模型 4.2 网络程序概览 4.3 socket的打开 4.4 socket的命名 4.4.1 sockaddr结构 4.4.2 sockaddr_in结构 4.4.3 端口号 4.4.4 本地IP地址 4.4.5 什么是socket名称 4.4.6 客户端socket名称是可选的 4.5 与另一个socket建立关联 4.5.1 服务器如何准备建立关联 4.5.2 客户端如何发起一个关联 4.5.3 服务器如何完成一个关联 4.6 socket之间的发送与接收 4.6.1 在“已连接的”socket上发送数据 4.6.2 在“无连接的”socket上发送数据 4.6.3 接收数据 4.6.4 socket解复用器中的关联 4.7 socket的关闭 4.7.1 closesocket 4.7.2 shutdown 4.8 客户端和服务器概览 第5章 操作模式 5.1 什么是操作模式 5.1.1 不挂机,等待:阻塞 5.1.2 挂机后再拨:非阻塞 5.1.3 请求对方回拨:异步 5.2 阻塞模式 5.2.1 阻塞socket 5.2.2 阻塞函数 5.2.3 伪阻塞的问题 5.2.4 阻塞钩子函数 5.2.5 阻塞情境 5.2.6 撤销阻塞操作 5.2.7 阻塞操作中的超时 5.2.8 无最少接收限制值 5.2.9 代码示例 5.3 非阻塞模式 5.3.1 怎样使socket成为非阻塞的 5.3.2 成功与失败不是绝对的 5.3.3 探询而非阻塞 5.3.4 显式地避让 5.3.5 代码示例 5.4 异步模式 5.4.1 认识异步函数 5.4.2 撤销异步操作 5.4.3 代码示例 5.4.4 AU_T
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值