Winsock学习----面向连接的协议(一)
2015-03-25 15:15
218 查看
套接字有三种类型:流式套接字, 数据包套接字和原始套接字。其中流式套接字定义了一种可靠的面向连接的服务,实现了无差错无重复的顺序数据传输。数据报套接字定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证可靠,无差错。原始套接字允许对底层协议如ip和ICMP直接访问,主要用于新的网络协议实现测试等。
服务器API函数:
“服务器”其实就是一个进程, 它需要等待任意数量的客户端连接,以便为他们的请求提供服务。对服务器监听的连接来说,“服务器”必须在一个已知的名字上。在TCP/IP中,
这个名字就是本地接口的IP地址, 并加上一个端口号。每一种协议都有一套不同的定址方案,所以会有不同的命名方法。在Winsock中,
第一步是将指定的套接字绑定到它已知的名字上。这个过程是通过API调用bind来完成。下一步是这个套接字设置为监听模式。这时,用API函数listen来完成的。最后,若一个客户试图建立连接,服务器必须通过accept或者WSAAccept调用接受连接。
1.bind函数:
int bind(
SOCKET s,
const struct sockaddr FAR* name,
int namelen
)
s 代表我们希望在上面等待客户端连接的套接字。
name
它的 是一个指向struct sockaddr 类型的指针。sockaddr中包含了名字的地址和端口信息,以及使用的协议等。
namelen
这个参数表示的是 sockaddr 的大小。
示例代码:
SOCKET s;
struct sockaddr_in tcpaddr;
int port = 5150;
int nSockErr;
s = socket(AF_INET, SOCK_SREAM, IPPROTO_TCP);
tcpaddr.sin_family = AF_INET;
tcpaddr.sin_port = htons(port);
tcpaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(s, (SOCKADDR*)&tcpaddr, sizeof(tcpaddr)) == SOCKE_ERROR)
{
nSockErr = WSAGetLastError();
}
这个例子中创建了一个流套接字。随后, 设置了TCP/IP地址结构, 一边在它上面接受客户端连接。在这种情况下套接字绑定到端口5150上的默认IP接口。
一旦出错。bind就会返回SOCKET_ERROR。对bind来说最常见的错误是WSAEADDRINUSE。如果使用的是TCP/IP,那么WSAEADDRINUSE就代表另一个进程已经同本地IP接口和端口绑定到一起。或者那个IP或者端口号正处于TIME_WAIT状态。假如在调用bind的时候套接字已经绑定过了,便会返回WSAEFFAULT错误。
2.listen函数
int listen(
SOCKET s,
int backlog
);
第一个参数同样是绑定过的套接字。
第二个参数指定了正在等待连接的最大队列长度。这个参数非常重要,因为完全可能同时出现几个客户端连接请求。如果backlog为2,如果有3个客户端同时发出请求,那么头两个会被放在等待处理的队列中,以便应用程序能依次处理。而第三个请求连接会得到WSAECONNREFUSED错误。注意,一旦服务器接收了一个连接,那个连接就会从等待队列中删除掉,以便能接收继续接收请求。backlog本身的就存在着限制,这个限制是有基层的协议提供者决定的。如果出现非法值,会用最近进合法值取代。除此之外,对于如何知道实际的bakclog,其实并不存在一个标准手段。
listen的错误:listen的错误常见的有WSAEINVAL。这个错误意味着忘记在listen之前调用bind。
3.Accept和WSAAccept
SOCKET accept(
SOCKET s,
struct FAR* addr,
int FAR* addrlen
);
第一个参数 是一个已经处于监听状态的套接字。
第二个参数 是一个指向 sockaddr或者sockaddr_in 类型的指针, 这个结构体用来保存客户端的信息。
第三个参数 表示sockaddr或者sockaddr_in 结构的大小
通过调用accept函数,可以为上述等待队列中的第一个连接请求提供服务。accept函数返回后,addr结构中包含发出请求的客户端的ip地址信息。此外accept还会返回一个新的套接字描述符,它对应这已经接受连接的客户端连接。对于该客户端之后的所有操作都应该使用这个套接字。至于原来的监听套接字仍然处于监听状态。如果INVALID_SOCKET,这是我们需要调用WSAGetLastError已得到更多的错误细节。
SOCKET sServSock;
sockaddr_in addr;
int nSockErr;
int nNumConns[5];
SOCKET sConns[5];
sockaddr Connaddrs[5];
int nAddrLen = sizeof(sockaddr);
sServSock = socket(AF_INET, SOCK_SREAM, 0);
addr.sin_family = AF_INET;
addr.sin_port = hton(5050);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sServSock, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKE_ERROR)
{
nSockErr = WSAGetLastError();
}
if(listen(sServSock, 2) == SOCKET_ERROR)
{
nSockErr = WSAGetLastError();
}
while( (nNumconns<5))
{
sConns[nNumConns] = accept(sServSock, ConnAddrs[nNumConns],&nAddrLen);
if([b]sConns[nNumConns] == INVALID_SOCKET)[/b]
{
nSockErr = GetLastError();
}
else
{
nNumConns++;
}
}
服务器API函数:
“服务器”其实就是一个进程, 它需要等待任意数量的客户端连接,以便为他们的请求提供服务。对服务器监听的连接来说,“服务器”必须在一个已知的名字上。在TCP/IP中,
这个名字就是本地接口的IP地址, 并加上一个端口号。每一种协议都有一套不同的定址方案,所以会有不同的命名方法。在Winsock中,
第一步是将指定的套接字绑定到它已知的名字上。这个过程是通过API调用bind来完成。下一步是这个套接字设置为监听模式。这时,用API函数listen来完成的。最后,若一个客户试图建立连接,服务器必须通过accept或者WSAAccept调用接受连接。
1.bind函数:
int bind(
SOCKET s,
const struct sockaddr FAR* name,
int namelen
)
s 代表我们希望在上面等待客户端连接的套接字。
name
它的 是一个指向struct sockaddr 类型的指针。sockaddr中包含了名字的地址和端口信息,以及使用的协议等。
namelen
这个参数表示的是 sockaddr 的大小。
示例代码:
SOCKET s;
struct sockaddr_in tcpaddr;
int port = 5150;
int nSockErr;
s = socket(AF_INET, SOCK_SREAM, IPPROTO_TCP);
tcpaddr.sin_family = AF_INET;
tcpaddr.sin_port = htons(port);
tcpaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(s, (SOCKADDR*)&tcpaddr, sizeof(tcpaddr)) == SOCKE_ERROR)
{
nSockErr = WSAGetLastError();
}
这个例子中创建了一个流套接字。随后, 设置了TCP/IP地址结构, 一边在它上面接受客户端连接。在这种情况下套接字绑定到端口5150上的默认IP接口。
一旦出错。bind就会返回SOCKET_ERROR。对bind来说最常见的错误是WSAEADDRINUSE。如果使用的是TCP/IP,那么WSAEADDRINUSE就代表另一个进程已经同本地IP接口和端口绑定到一起。或者那个IP或者端口号正处于TIME_WAIT状态。假如在调用bind的时候套接字已经绑定过了,便会返回WSAEFFAULT错误。
2.listen函数
int listen(
SOCKET s,
int backlog
);
第一个参数同样是绑定过的套接字。
第二个参数指定了正在等待连接的最大队列长度。这个参数非常重要,因为完全可能同时出现几个客户端连接请求。如果backlog为2,如果有3个客户端同时发出请求,那么头两个会被放在等待处理的队列中,以便应用程序能依次处理。而第三个请求连接会得到WSAECONNREFUSED错误。注意,一旦服务器接收了一个连接,那个连接就会从等待队列中删除掉,以便能接收继续接收请求。backlog本身的就存在着限制,这个限制是有基层的协议提供者决定的。如果出现非法值,会用最近进合法值取代。除此之外,对于如何知道实际的bakclog,其实并不存在一个标准手段。
listen的错误:listen的错误常见的有WSAEINVAL。这个错误意味着忘记在listen之前调用bind。
3.Accept和WSAAccept
SOCKET accept(
SOCKET s,
struct FAR* addr,
int FAR* addrlen
);
第一个参数 是一个已经处于监听状态的套接字。
第二个参数 是一个指向 sockaddr或者sockaddr_in 类型的指针, 这个结构体用来保存客户端的信息。
第三个参数 表示sockaddr或者sockaddr_in 结构的大小
通过调用accept函数,可以为上述等待队列中的第一个连接请求提供服务。accept函数返回后,addr结构中包含发出请求的客户端的ip地址信息。此外accept还会返回一个新的套接字描述符,它对应这已经接受连接的客户端连接。对于该客户端之后的所有操作都应该使用这个套接字。至于原来的监听套接字仍然处于监听状态。如果INVALID_SOCKET,这是我们需要调用WSAGetLastError已得到更多的错误细节。
SOCKET sServSock;
sockaddr_in addr;
int nSockErr;
int nNumConns[5];
SOCKET sConns[5];
sockaddr Connaddrs[5];
int nAddrLen = sizeof(sockaddr);
sServSock = socket(AF_INET, SOCK_SREAM, 0);
addr.sin_family = AF_INET;
addr.sin_port = hton(5050);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sServSock, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKE_ERROR)
{
nSockErr = WSAGetLastError();
}
if(listen(sServSock, 2) == SOCKET_ERROR)
{
nSockErr = WSAGetLastError();
}
while( (nNumconns<5))
{
sConns[nNumConns] = accept(sServSock, ConnAddrs[nNumConns],&nAddrLen);
if([b]sConns[nNumConns] == INVALID_SOCKET)[/b]
{
nSockErr = GetLastError();
}
else
{
nNumConns++;
}
}
相关文章推荐
- Linux Socket学习--面向非连接的协议
- BT源代码学习心得(十三):客户端源代码分析(对等客户的连接建立及其握手协议)
- Winsock编程入门 -- 4.面向连接的通讯
- WinSock网络编程学习笔记(七):协议查询程序(getprotobyname和getprotobynumber函数)
- Winsock协议配置问题导致网络连接出问题
- Socket网络编程学习笔记(2):面向连接的Socket
- BT源代码学习心得(十三):客户端源代码分析(对等客户的连接建立及其握手协议)
- Windows的网络编程-之三-面向无连接的协议
- Linux网络编程——无连接和面向连接协议的区别
- 学习笔记《实战Linux Socket编程》第六章 面向非连接的协议
- 基于 TCP (面向连接)和无连接UDP协议的 socket 套接字编程
- 基于 TCP (面向连接)和无连接UDP协议的 socket 套接字编程
- TCPIP-TCP是一种面向连接(连接导向)的、可靠的、基于字节流的运输层(Transport layer)通信协议
- 面向连接的协议 [2 ]
- Socket网络编程学习笔记(2):面向连接的Socket
- tcp协议是面向连接的,而http是无状态的,面向连接和无状态怎么感觉好像优点矛盾呢?
- 面向连接的协议 [1]
- C/C++日常学习总结(第八篇)winsock建立连接的步骤&窗口的生成
- Linux网络编程——连接和面向连接的协议之间没有区别
- Windows的网络编程-之二-面向连接的协议