windows 网络编程[转]

利用winsock编写网络应用程序服务端的步骤简述如下
WSAStartup 初始化网络编程库
socket 创建套接字
bind 指定地址、端口,绑定套接字
listen 进入监听状态
accept 等待接收新连接
send/recv 收发数据
closesocket 关键套接字
WSAStartup 释放对动态库的使用

下面详细介绍各API
1. Winsock初始化
调用int WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData )函数
WSAStartup,即WSA(Windows SocKNDs Asynchronous,Windows异步套接字)的启动命令。是Windows下的网络编程接口软件Winsock1 或 Winsock2 里面的一个命令(Ps:Winsock 是由Unix下的BSD Socket发展而来,是一个与网络协议无关的编程接口)。
为了在应用程序当中调用任何一个Winsock API函数,首先第一件事情就是必须通过WSAStartup函数完成对Winsock服务的初始化,因此需要调用WSAStartup函数。使用Socket的程序在使用Socket之前必须调用WSAStartup函数。

WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested=MAKEWORD(2,2);

if(WSAStartup(wVersionRequested,&wsaData)!=0)
{

//初始化失败

}

if(wsaData.wVersion != wVersionRequested)
{

//版本不匹配

}

2. 创建套接字

int socket(int domain, int type, int protocol);
函数说明:
第一个参数指定应用程序使用的通信协议的协议族,对于TCP/IP协议族,该参数置AF_INET;
第二个参数指定要创建的套接字类型,流套接字类型为SOCK_STREAM、数据报套接字类型为SOCK_DGRAM、原始套接字SOCK_RAW(WinSock接口并不适用某种特定的协议去封装它,而是由程序自行处理数据包以及协议首部);
第三个参数指定应用程序所使用的通信协议。此参数可以指定单个协议系列中的不同传输协议。在Internet通讯域中,此参数一般取值为0,系统会根据套接字的类型决定应使用的传输层协议。
返回值:成功返回套接字描述符,否则返回INVALID_SOCKET。

例子:
if ((m_sk = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{

//创建套接字失败

}

3. 绑定套接字

地址结构的定义:

/*

* Socket address, internet style.

*/
struct sockaddr_in {
short sin_family; //协议族
u_short sin_port; //端口号
struct in_addr sin_addr; //地址信息
char sin_zero[8];
};

/*
* Internet address (old style... should be updated)
*/
struct in_addr {
union {
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { u_short s_w1,s_w2; } S_un_w;
u_long S_addr;
} S_un;

#define s_addr S_un.S_addr

/* can be used for most tcp & ip code */

/*

* Structure used by kernel to store most

* addresses.

*/

struct sockaddr {

u_short sa_family; /* address family */

char sa_data[14]; /* up to 14 bytes of direct address */

};

注意:s_addr是一个宏,可以方便设置地址

#define s_addr  S_un.S_addr
                                /* can be used for most tcp & ip code */
/*
     * Structure used by kernel to store most
     * addresses.
*/
struct sockaddr {
        u_short sa_family;              /* address family */
        char    sa_data[14];            /* up to 14 bytes of direct address */
};
注意:s_addr是一个宏,可以方便设置地址
上述定义在winsock2.h中
绑定函数原型:
int bind( int sockfd , const struct sockaddr * my_addr, socklen_t addrlen);
函数说明:
参数列表中,sockfd 表示已经建立的socket编号(描述符);
  my_addr 是一个指向sockaddr结构体类型的指针;
参数addrlen表示my_addr结构的长度,可以用sizeof函数获得。

例子:
sockaddr_in addr;
    addr.sin_family = AF_INET; //使用互联网际协议,即IP协议
    addr.sin_port = htons(port);
addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
IP地址参数为INADDR_ANY,则由系统内核来自动指定
port为0,则由系统自动指派一个1024~5000之间惟一的端口号

if (bind(m_sk, (sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
{
    //绑定出错
}

4. 进入监听状态

int listen(int s, int backlog);
函数说明:
s:已绑定的套接字
backlog:同时能处理的最大连接数
Listen()并未开始接收连线, 只是设置socket 为listen 模式, 真正接收client 端连线的是accept(). 通常listen()会在socket(), bind()之后调用, 接着才调用accept()。

5. 接受连接

int accept(int s,struct sockaddr * addr,int * addrlen); 
当有新的连接到来时,accept返回一个新的套接字描述符。连接请求端的相关信息存储在addr中。
参数sockfd
参数sockfd是监听套接字,这个套接字用来监听一个端口,当有一个客户与服务器连接时,它使用这个端口号,而此时这个端口号正与这个套接字关联。当然客户不知道套接字这些细节,它只知道一个地址和一个端口号。
参数addr
这是一个结果参数,它用来接受一个返回值,这返回值指定客户端的地址,当然这个地址是通过某个地址结构来描述的,用户应该知道这一个什么样的地址结构。如果对客户的地址不感兴趣,那么可以把这个值设置为NULL。
参数len
也是结果的参数,用来接受上述addr的结构的大小的,它指明addr结构所占有的字节个数。同样的,它也可以被设置为NULL。

如果accept成功返回,则服务器与客户已经正确建立连接了,此时服务器通过accept返回的套接字来完成与客户的通信

6. 收发数据

int send(int s, const void *buf, int len, int flags);
int recv(int s, void *buf, int len, int flags);
函数返回实际收发的字节数。出错返回-1, 需要关闭此连接。
函数缺省是阻塞函数,直到发送/接收完成。
注意:如果send 函数返回值与参数len 不相等,则剩余的未发送信息需要再次发送
recv接收到数据之后不会在末尾添加’\0’。

7. 其它API

WSAGetLastError()
获取上次失败操作的错误状态
closesocket(int socket)
关闭套接字
WSACleanup()
终止Winsock 2 DLL (Ws2_32.dll) 的使用

时间: 2024-08-24 17:27:54

windows 网络编程[转]的相关文章

Windows网络编程经验小结

转自:CSDN网友的强贴,其ID:gdy119 (夜风微凉) 1. 如果在已经处于 ESTABLISHED状态下的socket(一般由端口号和标志符区分)调用closesocket(一般不会立即关闭而经历TIME_WAIT的过程)后想继续重用该socket: BOOL bReuseaddr=TRUE; setsockopt(s,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(BOOL)); 2. 如果要已经处于连接状态的soket

Windows网络编程

第一章 序言 我写这个专题的目的,一方面是为了通过对网络编程再一次系统的总结,提高自己的网络编程水平,特别是Windows下的网络编程水平.同一时候,我也希望,能为众多初学网络编程的人提供一点帮助,由于我開始学习网络编程的时候,能找到的资料就非常少.当然,花钱能够买到翻译版本号的书:) 首先向大家推荐一本非常好的參考书,Network Programming for Microsoft Windows 2nd, 初学网络编程的时候我还不知道有这样一本好书,仅仅是上各大论坛把能找到的网络编程方面的

Windows网络编程 2 【转】

Windows网络编程使用winsock.Winsock是一个基于Socket模型的API,在Windows系统中广泛使用.使用Winsock进行网络编程需要包含头文件Winsock2.h,需要使用库ws2_32.lib,包含方法:可以使用语句来告诉编译器连接该库#pragma comment(lib, “ws2_32.lib”);如果使用VS,可以通过“项目” --> “XX属性”--> “连接器”-->“输入”--> “附加依赖项”添加ws2_32.lib. (XX为当前工程名

windows网络编程的一些理论

参考自<VC++深入详解> 这是我在看书时记录下来的东西. 注:下面的Socket其实都应该是socket 第14章网络编程 Socket是连接应用程序与网络驱动程序的桥梁,Socket在应用程序中创建,通过绑定与驱动程序建立关系. 此后,应用程序给Socket的数据,由Socket交给驱动程序向网络上发送出去. 计算机从网络上收到与该Socket绑定的IP地址和端口号相关的数据后,由驱动程序交给Socket,应用程序便可从该Socket中提取接收到的数据. 14.1 计算机网络基本知识. 1

72&gt;&gt;Windows 网络编程

1 网络编程 API 2 3 4 int WSAStartup( WORD wVersionRequested, LPWSADATA lpWSAData ); lpWSAData 是一个返回值:成功返回 0,失败返回 -1,错误代码 WSASYSNOTREADY 表示基础网络子系统没有准备好网络通行,WSAVERNOTSUPPORTED 表示 Socket 版本不支持,WSAEINPROGRESS 表示一个阻塞的 Sockets 操作在进程中,WSAEPROCLIM 表示 Sockets 支持的

Windows 网络编程(2)--重叠I/0模型

5).重叠I/O模式(overlapped) 常用函素: 1.WSASocket : 创建套接字 2.TCP WSASend WSARecv 3.UDP: WSASendTo WSARecvFrom 4.AccepEx (Mswsock.lib库导出) WSAIoctl 5.数据类型 WSAOVERLAPPED (wsaoverlapped) 函数: WSAGetOverlappedResult 使用: 缓冲区对象 typedef struct _BUFFER_OBJ { OVERLAPPED

windows网络编程中文 笔记(二)

IPv4 地址段 IPv4地址类别 种类 网络部分 第1个数字 端点数字 A  8位  0-127  16777216 B  16位  128-191  65526 C  24位  193-223  256 D  N/A  224~239  N/A E   N/A  240~255   N/A 1. A类地址(1)A类地址第1字节为网络地址,其它3个字节为主机地址.(2)A类地址范围:1.0.0.1-126.255.255.254(3)A类地址中的私有地址和保留地址:① 10.X.X.X是私有地

Windows网络编程--选择(select)模型

选择模型是I/O模型中最简单的一个.Server端通过创建两个套接字集合fdOld和fdNew,在循环中通过事件添加和移除未决IO套接字句柄.测试的时候先启动服务端再启动客户端. 以下为Server端源代码(在VS2010下测试通过): #include "stdafx.h"#include<WinSock2.h>#include<Windows.h> #include<iostream> #pragma comment(lib,"ws2_

windows网络编程入门

windows Sockets 的版本: 头文件:WINSOCK.h 库文件:wsock32.lib 动态困:WINSOCK.DLL 头文件:WINSOCK2.h 库文件:WS2_32.lib 动态困:WS2_32.DLL 服务端: WSADATA wsd; //WSADATA变量 SOCKET sServer; //服务器套接字 SOCKET sClient; //客户端套接字 SOCKADDR_IN addrServ;; //服务器地址 char buf[ BUF_SIZE]; //接收数据