基于
WinSocket
的单线程
Server
的实现
功能描述:
程序实现一个Server监听端口的功能,运行后,其处于监听状态。当有Client连接到此Server,它停止监听,接收到自此client的数据,并将从Client收到数据反射给Client。
调用顺序:
1.
WSAStartup:开始对WS2_32.dll的使用。
2.
socket:创建一个socket。
3.
bind:绑定IP与Port。
4.
listen:监听一个socket。
5.
accept:接受client的连接。
6.
send:向指定socket发送数据。
7.
recv:从指定的socket接收数据。
8.
WSACleanup:关闭对WS2_32.dll的使用。
函数说明;
int WSAStartup(
WORD wVersionRequested,
LPWSADATA wVersionRequested,
LPWSADATA lpWSAData
);
功能:启动WS2_32.dll,将将获得的Winsocket实现的详细信息保存到lpMSAData所指向的数据结构中,调用此函数后才可以使用Winsocket相关的函数。
//Initialize a WSADATA object
WSADATA wsaData;
int nResult = WSAStartup(MAKEWORD(2,2),&wsaData);
|
SOCKET socket(
int af,
int af,
int type,
int protocol
);
功能:创建一个绑定到指定service provider上的socket。
//Create a socket
SOCKET m_socket;
m_socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
|
int bind(
SOCKET s,
const struct sockaddr* s,
const struct sockaddr* name,
int namelen
);
功能:将本地地址与一个socket绑定。
//Bind a socket
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("127.0.0.1");
service.sin_port = htons(27002);
if(bind(m_socket,(SOCKADDR*)&service,sizeof(service)) == SOCKET_ERROR){
cout << "Error at bind " << endl;
closesocket(m_socket);
return 1;
}
|
int listen(
SOCKET s,
int s,
int backlog
);
功能:将一个socket置于监听状态。
//listen on a socket
if(listen(m_socket,20) == SOCKET_ERROR){
cout << "Error on listen" << endl;
return 1;
}
|
SOCKET accept(
SOCKET s,
struct sockaddr* s,
struct sockaddr* addr,
int* addrlen
);
功能:接受来自外部的Client连接,返回一个新的socket。
AcceptSocket = SOCKET_ERROR;
while (AcceptSocket == SOCKET_ERROR) {
AcceptSocket = accept(m_socket,NULL,NULL);
}
|
int recv(
SOCKET s,
char* s,
char* buf,
int len,
int len,
int flags
);
功能:从指定的socket中接收数据。
int nSendBytes = 0;
int nRecvBytes = 0;
char pRecvBytes[32] = "";
nRecvBytes = recv(m_socket,pRecvBytes,32,0);
cout << "Num of receive :" << nRecvBytes << endl;
cout << pRecvBytes << endl;
|
int send(
SOCKET s,
const char* s,
const char* buf,
int len,
int len,
int flags
);
功能:向已连接的socket发送数据。
char pSendBytes[32] = "Server:Send data";
nSendBytes = send(m_socket,pSendBytes,32,0);
|
int WSACleanup(void);
功能:关闭能WS2_32.dll的使用,调用次数应该与WSAStartup相同。
WSACleanup();
|
完整代码
#include
<iostream>
#include
"winsock2.h"
#include
<windows.h>
using
namespace std;
int
main(){
//启动WS2_32.dll
WSADATA wsaData;
int nResult = WSAStartup(MAKEWORD(2,2),&wsaData);
if(nResult != NO_ERROR){
cout << "Error at WSAStartup" << endl;
return 1;
}
//创建一个socket
SOCKET m_socket;
m_socket = socket(AF_INET, //协议族
SOCK_STREAM, //SOCKET类型
IPPROTO_TCP); //此socket使用的协议
if(m_socket == INVALID_SOCKET){
cout << "Error at socket " << WSAGetLastError() << endl;
WSACleanup();
return 1;
}
//Bind a socket
sockaddr_in service;
service.sin_family = AF_INET;//协议族
service.sin_addr.s_addr = inet_addr("127.0.0.1");//IP地址
service.sin_port = htons(27002); //端口号
//将socket与指定的地址绑定
if(bind(m_socket,(SOCKADDR*)&service,sizeof(service)) == SOCKET_ERROR){
cout << "Error at bind " << endl;
closesocket(m_socket);
return 1;
}
//监听socket
if(listen(m_socket,20) == SOCKET_ERROR){
cout << "Error on listen" << endl;
return 1;
}
//接受一个socket连接
SOCKET AcceptSocket;
cout << "Waiting for client to connect" << endl;
while (1) {
AcceptSocket = SOCKET_ERROR;
while (AcceptSocket == SOCKET_ERROR) {
AcceptSocket = accept(m_socket,NULL,NULL);
}
cout << "client connected!" << endl;
m_socket = AcceptSocket;
break;
}
int nSendBytes = 0;
int nRecvBytes = 0;
char pSendBytes[32] = "Server:Send data";
char pRecvBytes[32] = "";
//从socket接收数据.
nRecvBytes = recv(m_socket,pRecvBytes,32,0);
cout << "Num of receive :" << nRecvBytes << endl;
cout << pRecvBytes << endl;
//向socket发送数据。
nSendBytes = send(m_socket,pSendBytes,32,0);
if (nSendBytes == SOCKET_ERROR) {
int nErr = WSAGetLastError();
WSAEACCES;
cout << nErr << endl;
}else
cout <<"Num of send : " << nSendBytes << endl;
//清除WS2_32.dll
Sleep(5000);
WSACleanup();
return 0;
}
|