函数简介:
// 创建套接字
// @param af 通信区域,AF_UNIX、AF_INET(国际网区域)、AF_NS等,DOS、WINDOWS仅支持AF_INET
// @param type 套接字类型,SOCK_STREAM(TCP流式套接字,面向连接可靠的数据传输,可控制流量,数据长度无限制)、SOCK_DGRAM(数据包式套接字,无连接服务,数据包以独立包形式发送)、SOCK_RAW(原始式套接字,允许对较低层协议IP、ICMP等直接访问)
// @param protocol协议,0为默认连接模式
// @return 套接字号
SOCKET PASCAL FAR socket(int af, int type, int protocol)
// 绑定套接字地址与套接字号
// @param s 套接字号,由socket函数返回
// @param name 本地地址
// @param namelen name的长度
// @return 0绑定成功,SOCKET_ERROR绑定失败
int PASCAL FAR bind(SOCKET s, const struct sockaddr FAR * name, int namelen)
// 监听连接
// @param s 套接字号,由socket函数返回
// @paaram backlog请求连接队列的最大长度,用于限制排队请求的个数
// @return 0监听成功,SOCKET_ERROR监听失败
int PASCAL FAR listen(SOCKET s, int backlog)
// 建立连接
// @param s 本地套接字号,由socket函数返回
// @param name 对方套接字地址
// @param namelen对方套接字地址长度
// @return 0建立成功,SOCKET_ERROR建立失败
int PASCAL FAR connect(SOCKET s, const struct sockaddr FAR * name, int namelen)
// 接受连接
// @param s 本地套接字号,由socket函数返回
// @param addr 客户端套接字地址
// @param addrlen客户端套接字地址长度
// @return 接受套接字,用于向客户端发送数据,INVALID_SOCKET接受失败
SOCKET PASCAL FAR accept(SOCKET s, struct socaddrFAR * addr, int FAR * addrlen)
// 数据发送
// @param s 本地套接字号,由socket函数返回
// @param buf 发送的数据缓冲区指针
// @param len 发送的数据长度
// @param flags 传输控制方式,是否发送带外数据
// @return 发送的字节数,SOCKET_ERROR发送失败
int PASCAL FAR send(SOCKET s, const char FAR * buf, int len, int flags)
// 数据接收
// @param s 通信套接字号
// @param buf 接收数据缓冲区
// @param len 接收数据长度
// @param flags 是否接收带外数据
// @return 接收的字节数,0 连接已关闭,SOCKET_ERROR接收失败
int PASCAL FAR recv(SOCKET s, char FAR * buf, int len, int flags)
// 套接字状态检测
// @param readfds 做读检测的套接字描述符结合的指针
// @param writefds 做写监测的套接字描述符集合的指针
// @param exceptfds 做是否出错的套接字描述符结合的指针
// @param timeout 该函数等待的最大时间,NULL为阻塞操作
// @return 返回fd_set中的套接字描述符的总数目,SOCKET_ERROR检测失败
int PASCAL FAR select(int nfds, fd_set FAR *readfds, fd_set FAR *writefds, fd_set FAR *exceptfds, const struct timeval FAR * timeout)
// 关闭套接字
// @param s 要关闭的套接字
// @return 0关闭成功,SOCKET_ERROR关闭失败
BOOL PASCAL FAR closesocket(SOCKET s)
// 设置套接口
// @param sockfd 标识一个套接口的描述字
// @param level 选项定义的层次
// @param optname 需设置的选项
// @param optval 选项值指针
// @param optlen 选项值长度
// @return 0设置成功,SOCKET_ERROR设置套接口错误
/*
level: SOL_SOCKET (基本套接口)
IPPROTO_TCP (TCP套接口)
IPPROTO_IP (IPV4套接口)
IPPROTO_IPV6(IPV6套接口)
optname: --------------------SOL_SOCKET--------------------------
SO_BROADCAST(BOOL, 是否允许发送广播消息,适用于UDP)
SO_DEBUG (BOOL, 是否允许记录调试信息)
SO_DONTROUTE(BOOL, 是否禁止查找路由)
SO_KEEPALIVE(BOOL, 是否保持连接,主要用于对方主机的活动检测)
SO_OOBINLINE(BOOL, 是否在常规数据流中接收带外数据)
SO_REUSEADDR(BOOL, 是否允许重用本地地址和端口,主要用于关闭后需要重用该socket)
SO_EXCLUSIVEADDRUSE(BOOL, 是否独占模式使用端口,主要用于防止程序被监听)
SO_ACCEPTCONN(BOOL,套接口在监听)
TCP_NODELAY (BOOL 禁止发送合并的Nagle算法)
SO_DONTLINER(BOOL, 是否有未发送数据时阻塞关闭操作)
SO_LINGER (struct linger FAR* 如关闭时有未发送数据,则延迟关闭,同SO_DONTLINER)
SO_RCVBUF (int, 接收缓冲区大小,主要用于较大包的接收,0时,不会从socket缓冲区拷贝到系统缓冲区)
SO_SNDBUF (int, 发送缓冲区大小,主要用于较大包的发送,0时,不会从系统缓冲区拷贝到socket缓冲区)
SO_RCVLOWAT (int,接收缓冲区下限,缺省1)
SO_SNDLOWAT (int,发送缓冲区下限,TCP缺省2048)
SO_RCVTIMEO(struct timeval, 接收超时)
SO_SNDTIMEO(struct timeval, 发送超时)
SO_ERROR (int, 获取错误状态并清除)
SO_TYPE (int, 套接口类型)
SO_BSDCOMPAT(int,与BSD系统兼容)
IP_OPTIONS 在IP头中设置选项。
参考:http://blog.csdn.net/chary8088/article/details/2486377
示例:
BOOL bOn = TRUE;
setsockopt(s, SOL_SOCKET,SO_REUSEADDR, (const char* )&bOn, sizeof(BOOL));
int nTimeout = 1000;
setsockopt(s, SOL_SOCKET,SO_SNDTIMEO, (char*)&nTimeout, sizeof(int));
*/
int setsockopt(int sockfd,int level, int optname,const void *optval, socklen_t optlen)
服务端示例代码:
#include "stdafx.h"
#include <stdio.h>
#include <Winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "mswsock.lib")
int _tmain(int argc, _TCHAR* argv[])
{
//加载释放winsock库
WSADATA wsaData;
if(WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
{
printf("%s\n", "Load WinSock Error.");
return 0;
}
if(LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
{
WSACleanup( );
return 0;
}
//创建套接字
SOCKET svrSocket = socket(AF_INET, SOCK_STREAM, 0);
//绑定套接字,配置监听地址和端口
SOCKADDR_IN svrAddr;
ZeroMemory((char*)&svrAddr, sizeof(svrAddr));
svrAddr.sin_family = AF_INET; //国际网区域
svrAddr.sin_port = htons(6000); //监听端口
svrAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //有IP
if(bind(svrSocket, (SOCKADDR*)&svrAddr, sizeof(SOCKADDR)) == SOCKET_ERROR)
{
printf("Bind Socket Error:%d\n", WSAGetLastError());
return 0;
}
//监听
if(listen(svrSocket, 5) == SOCKET_ERROR)//最大连接数5个
{
printf("Start Listen Error:%d\n", WSAGetLastError());
return 0;
}
printf("Start Listen Succ...\n");
//接收套接字
SOCKADDR_IN clientAddr;
SOCKET connSocket;
int length = sizeof(SOCKADDR);
char cExist = ' ';
while(cExist != 'q')
{
//接收连接
if((connSocket = accept(svrSocket, (SOCKADDR*)&clientAddr, &length)) == INVALID_SOCKET)
{
printf("Accept Error:%d\n", WSAGetLastError());
return 0;
}
//发送连接消息
char sendBuff[512];
sprintf_s(sendBuff, "server:you have connected, %s", inet_ntoa(clientAddr.sin_addr));
if(send(connSocket, sendBuff, strlen(sendBuff) + 1, 0) == SOCKET_ERROR)
{
printf("Send Error:%d\n", WSAGetLastError());
return 0;
}
//接收客户端消息
char recvBuff[512];
if(recv(connSocket, recvBuff, 512, 0) == SOCKET_ERROR)
{
printf("Recieve Error:%d\n", WSAGetLastError());
return 0;
}
printf("%s\n", recvBuff);
cExist = getchar();
}
//关闭连接、释放资源
closesocket(svrSocket);
closesocket(connSocket);
WSACleanup();
}
客户端示例代码:
// sockClient.cpp : 定义控制台应用程序的入口点。
// 客户端程序
#include "stdafx.h"
#include <Winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "mswsock.lib")
int _tmain(int argc, _TCHAR* argv[])
{
//加载释放winsock库
WSADATA wsaData;
if(WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
{
printf("%s\n", "Load WinSock Error.");
return 0;
}
if(LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
{
WSACleanup( );
return 0;
}
//创建套接字
SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, 0);
//与服务端连接
SOCKADDR_IN svrAddr;
ZeroMemory((char*)&svrAddr, sizeof(svrAddr));
svrAddr.sin_family = AF_INET; //国际网区域
svrAddr.sin_port = htons(6000); //监听端口
svrAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //服务端IP
if(connect(clientSocket, (SOCKADDR*)&svrAddr, sizeof(SOCKADDR)) == SOCKET_ERROR)
{
printf("Bind Socket Error:%d\n", WSAGetLastError());
return 0;
}
printf("Connect Server Succ...\n");
//发送消息
char sendBuff[512];
sprintf_s(sendBuff, "client:hello,server!");
if(send(clientSocket, sendBuff, strlen(sendBuff) + 1, 0) == SOCKET_ERROR)
{
printf("Send Error:%d\n", WSAGetLastError());
return 0;
}
//接收服务端消息
char recvBuff[512];
if(recv(clientSocket, recvBuff, 512, 0) == SOCKET_ERROR)
{
printf("Recieve Error:%d\n", WSAGetLastError());
return 0;
}
printf("%s\n", recvBuff);
//关闭连接、释放资源
closesocket(clientSocket);
WSACleanup();
getchar();
return 0;
}
注:当发生错误退出时,没有断开连接、释放资源。