服务器端:
客户端:
socket()
用于创建与指定的服务提供者绑定套接字,如果成功则返回新的socket句柄,否则返回INVALID_SOCKET.
SOCKET socket(
int af, /*指定协议的地址家族,通常使用AF_INET*/
int type, /*指定套接字类型*/
int protocol /*套接字的协议*/
);
套接字类型 | 说明 |
---|---|
SOCKET_STREAM | 提供顺序、可靠、双向和面向连接的字节数据传输机制,使用TCP |
SOCKET_DGRAM | 支持无连接的数据报,使用UDP |
SOCKET_RAM | 原始套接字,用于接收本机网卡上的数据帧或数据包 |
bind()
将本地地址与socket绑定在一起,如果未发生错误,则返回0,否则返回SOCKET_ERROR.
int bind(
SOCKET s, /*标识一个未绑定的Socket的描述符*/
const struct sockaddr FAR * name, /*绑定到Socket的sockaddr结构体地址*/
int namelen /*参数name的长度*/
);
如果应用程序不关心分配给它的本地地址,则可以把地址设置未ADDR_ANY.
listen()
将套接字设置为监听接入连接的状态,如果未发生错误,则返回0,否则返回SOCKET_ERROR。可以调用WSAGetLastError()函数获取错误代码
int listen(
SOCKET s, /*指定一个已经绑定(bind)但尚未连接的套件字*/
int backlog /*指定等待连接队列的最大长度*/
);
accept()
服务器端调用listen()函数监听接入连接后,可以调用accept()函数来等待接受连接请求。如果函数调用成功,则返回一个新建的Socket句柄,该Socket用于实现服务器和客户端之间的通信。如果调用失败,则返回INVALID_SOCKET
SOCKET accept(
SOCKET s, /*设置为监听状态的Socket*/
struct sockaddr FAR * addr, /*输出参数,用于接收接入地址信息,如果不关注接入地址,可以设置为NULL,可选*/
int FAR * addrlen /*输出参数,指定接入地址的长度,可选*/
);
recv()
从已连接的Socket中接收数据。如果函数调用成功,则返回接收数据的字节数;如果连接已经关闭,则返回0;否则返回SOCKET_ERROC.
int recv(
SOCKET s, /*已连接的Socket*/
char FAR * buf, /*用于接收数据的缓存区*/
int len, /**缓冲区的长度/
int flags /*用于影响函数的行为*/
);
参数flag的可选值 | 说明 |
---|---|
MSG_PEEK | 数据将复制到缓冲区buf中,但并不从输入队列中移除这些数据 |
MSG_OOB | 处理带外数据 |
send()
在已建立连接的Socket上发送数据。如果函数调用成功,则返回发送数据的字节数,可以小于参数len中指定的长度;如果出现错误,则返回SOCKET_ERROC.
int send(
SOCKET s, /*已连接的Socket*/
const char FAR * buf, /*要发送数据的缓存区*/
int len, /*buf缓冲区的长度*/
int flags /*用于影响函数的行为*/
);
参数flag的可选值 | 说明 |
---|---|
0 | 指定该函数没有特殊行为 |
MSG_DONTROUTE | 指定数据不选择路由 |
MSG_OOB | 从带外发送数据 |
closesocket()
关闭一个Socket,释放其所占用的资源。如果没有错误则返回0;否则返回SOCKET_ERROC.
int closesocket(
SOCKET s /*要关闭的Socket*/
);
shutdown()
禁止在指定的Socket上发送和接收数据。如果没有错误则返回0;否则返回SOCKET_ERROC.
int shutdown(
SOCKET s, /*要关闭的Socket*/
int how /*指定禁用的操作*/
);
参数how的选项 | 说明 |
---|---|
SD_RECEIVE | 不允许调用recv()接收数据 |
SD_SEND | 不允许调用send()发送数据 |
SD_BOTH | 不允许发送接收数据 |
connect()
用于建立到Socket的连接,该Socket必须处于监听状态。如果没有错误则返回0;否则返回SOCKET_ERROC.
int connect(
SOCKET s, /*未连接的Socket句柄*/
const struct sockaddr FAR * name, /*指定要连接的Socket的名称*/
int namelen /*指定Socket名的长度*/
);
TCP服务器端:
#include
#include
#include
#pragma comment(lib,"WS2_32.lib")
#define BUF_SIZE 64 //服务器接收数据缓冲区大小
int _tmain(int argc,_TCHAR* argv[])
{
//初始化WindowsSocket
WSADATA wsd;
SOCKET sServer;
SOCKET sClient;
int retVal; //调用各种socket函数的返回值
char buf[BUF_SIZE];
//初始化Socket动态库
if(WSAStartup(MAKEWORD(2,2),&wsd)!=0){
printf("WSASTARTUP Failed!\n");
return 1;
}
//创建用于监听的socket
sServer = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (INVALID_SOCKET == sServer)
{
printf("socket failed!\n");
WSACleanup();
return -1;
}
//设置服务器Socket地址
SOCKADDR_IN addrServ;
addrServ.sin_family = AF_INET; //地址家族,TCP
addrServ.sin_port = htons(9990); //端口
addrServ.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //地址
//绑定socket server到本地
retVal = bind(sServer,(const struct sockaddr*)&addrServ,sizeof(SOCKADDR_IN));
if (SOCKET_ERROR == retVal)
{
printf("bind failed!\n");
closesocket(sServer);
WSACleanup();
return -1;
}
//在socketscrver上进行监听
retVal = listen(sServer,1 );
if (SOCKET_ERROR == retVal)
{
printf("listen failed!\n");
closesocket(sServer);
WSACleanup();
return -1;
}
//接收请求
printf("TCP server start...\n");
sockaddr_in addrClient; //客户端地址
int addrClientLen = sizeof(addrClient);
sClient = accept(sServer,(sockaddr FAR*)&addrClient,&addrClientLen);
if (INVALID_SOCKET == sClient)
{
printf("accept failed\n");
closesocket(sServer);
WSACleanup();
return -1;
}
while(true)
{
ZeroMemory(buf,BUF_SIZE);
retVal = recv(sClient,buf,BUFSIZ,0);
if (SOCKET_ERROR == retVal)
{
printf("recv failed\n");
closesocket(sServer);
closesocket(sClient);
WSACleanup();
return -1;
}
//获取当前系统时间
SYSTEMTIME st;
GetLocalTime(&st);
char sDataTime[30];
sprintf(sDataTime,"%4d-%2d-%2d %2d:%2d:%2d",st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond);
printf("%s,Recv From Cliet [%s:%d] :%s\n",sDataTime,inet_ntoa(addrClient.sin_addr),addrClient.sin_port,buf);
//如果客户端发送字符串为quit,则退出
if(strcmp(buf,"quit")==0){
retVal = send(sClient,"quit",strlen("quit"),0);
break;
}
else{
char msg[BUF_SIZE];
sprintf(msg,"message received - %s",buf);
retVal = send(sClient,msg,sizeof(msg),0);
if(SOCKET_ERROR == retVal){
printf("send failed\n");
closesocket(sServer);
closesocket(sClient);
WSACleanup();
return -1;
}
}
}
//释放socket
closesocket(sServer);
closesocket(sClient);
WSACleanup();
system("pause");
}
TCP客户端:
#include
#include
#include
#include
#pragma comment(lib,"WS2_32.lib")
#define BUF_SIZE 64
int _tmain(int argc,_TCHAR* argv[])
{
WSADATA wsd;
SOCKET sHost;
SOCKADDR_IN servAddr;
char buf[BUF_SIZE];
int retVal;
//初始化socket
if (WSAStartup(MAKEWORD(2,2),&wsd)!=0)
{
printf("WSASTARTUP failed!\n");
return -1;
}
//创建socket
sHost = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(INVALID_SOCKET == sHost)
{
printf("socket failed\n");
WSACleanup();
return -1;
}
//设置服务器socket地址
servAddr.sin_family = AF_INET;
servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
servAddr.sin_port = htons(9990);
int sServerAddLen = sizeof(servAddr);
//连接服务器
retVal = connect(sHost,(LPSOCKADDR)&servAddr,sizeof(servAddr));
if(SOCKET_ERROR == retVal)
{
printf("connect failed\n");
closesocket(sHost);
WSACleanup();
return -1;
}
while(true)
{
printf("Input:");
std::string str;
std::getline(std::cin,str);
ZeroMemory(buf,BUF_SIZE);
strcpy(buf,str.c_str());
retVal = send(sHost,buf,strlen(buf),0);
if(SOCKET_ERROR == retVal)
{
printf("send failed\n");
closesocket(sHost);
WSACleanup();
return -1;
}
retVal = recv(sHost,buf,sizeof(buf)+1,0);
printf("Recv:%s\n",buf);
if (strcpy(buf,"quit")==0)
{
printf("quit!\n");
break;
}
}
closesocket(sHost);
WSACleanup();
system("pause");
return 0;
}