socket编程服务端的编写,经过一两天的努力终于将dos版本的服务端写好了。代码不多四十来行。首先来说说编写服务端的经过哪些步骤。其实 编写服务端其实不难。难的是 那些结构。眼换缭乱~~~
步骤1:加载套接字,对套接字进行初始化。(WSAStartup())
步骤2:创建一个套接字。(socket())
步骤3:绑定端口(bind())
步骤4:监听端口(listen())
步骤5:接受用户的请求(accept())此时的如果未接受到用户的请求会进入阻塞状态。一直等到获得请求为止。
接受了用户的请求也就保存到了套接字的一个句柄。同时也就意味着我们与目标主机建立了某种链接。此时我们就可以向它发送消息或者接受一个消息了。
后边要关闭套接字和卸载套接字
----------------------------
这样的话可以说服务端就已经编写好了。但是它只是接受一个用户的请求其它的功能是没有的
想要发送数据
send()函数
想要接受数据
recv()函数
------------------------------
函数介绍:
WSAStartup();
这个函数是初始化套接字,也叫加载套接字,它在头文件WinSock2.h头文件中定义如下:
int
WSAAPI
WSAStartup(
__in WORD wVersionRequested,
__out LPWSADATA lpWSAData
);
第一个参数:__in WORD wVersionRequested,它说明调用方可使用的最高版本分高低两个字节高位指出副版本,低位指出主版本
第二个参数:__out LPWSADATA lpWSAData用来指向WSADATA的一个指针,
接受sock实现的细节
socket()
这个函数用于创建一个套接字
定义如下:
socket(
__in int af,
__in int type,
__in int protocol
);
__in int af :一个地址描述。目前仅支持AF_INET格式,也就是说ARPA Internet地址格式。
__in int type:指定socket类型。新套接口的类型描述类型,如TCP(SOCK_STREAM)和UDP(SOCK_DGRAM)。常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等。
__in int protocol:顾名思义,就是指定协议。套接口所用的协议。如调用者不想指定,可用0。常用的协议有,IPPROTO_TCP、IPPROTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。如果协议protocol未指定(等于0),则使用缺省的连接方式。
bind()
将一本地地址与一套接口捆绑
原型如下
bind(
__in SOCKET s,
__in_bcount(namelen) const struct sockaddr FAR * name,
__in int namelen
);
__in SOCKET s,:标识一未捆绑套接口的描述字。
__in_bcount(namelen) const struct sockaddr FAR * name,:赋予套接口的地址
__in int namelen:name名字的长度。
listen()
listen(
__in SOCKET s,
__in int backlog
);
__in SOCKET s,用于标识一个已捆绑未连接套接口的描述字。
__in int backlog 等待连接队列的最大长度。1-5开区间取值
返回值
如无错误发生,listen()返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。
accept()
在一个套接口接受一个连接。
原型如下
SOCKET
WSAAPI
accept(
__in SOCKET s,
__out_bcount_opt(*addrlen) struct sockaddr FAR * addr,
__inout_opt int FAR * addrlen
);
__in SOCKET s,套接口描述字,该套接口在listen()后监听连接。
__out_bcount_opt(*addrlen) struct sockaddr FAR * addr,:指针,指向一缓冲区,其中接收为通讯层所知的连接实体的地址。Addr参数的实际格式由套接口创建时所产生的地址族确定。
addrlen:(可选)指针,输入参数,配合addr一起使用,指向存有addr地址长度的整型数。
返回值
成功返回一个新的套接字描述符,失败返回-1。
编写代码如下:
#include "head.h"
#include <WinSock2.h>
#include <Windows.h>
#pragma comment(lib,"WS2_32")
void main(int argc,TCHAR atga[])
{
//加载的套接字
WORD wvquest;
WSADATA WSAdata;
wvquest=MAKEWORD(2,2);
if (0!=WSAStartup(wvquest,(LPWSADATA)&WSAdata))
{
std::cout<<"加载套接字失败"<<std::endl;
}
//创建一个套接字
SOCKET m_socket =socket(AF_INET,SOCK_STREAM,0);
//绑定套接字
SOCKADDR_IN m_sockaddr;
m_sockaddr.sin_family=AF_INET;
m_sockaddr.sin_port=htons(3669);
m_sockaddr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
bind(m_socket,(sockaddr *)&m_sockaddr,sizeof(m_sockaddr));
//监听端口请求
listen(m_socket,4);
//等待客户请求
SOCKADDR_IN clientsock;
int len= sizeof(SOCKADDR_IN);
SOCKET Client;
while(1)
{
Client=accept(m_socket,(SOCKADDR *)&clientsock,&len);
std::cout<<"客户端请求响应成功!"<<std::endl;
char s[256]={0};
recv(Client,s,256,0);
std::cout<<s<<std::endl;
closesocket(Client);
}
std::cin.get();
std::cin.get();
closesocket(m_socket);
closesocket(Client);
WSACleanup();
}
功能呢演示:
输入:小甲鱼
输入www.fishc.com
输入牡丹是坏人:
演示结束现在开始说明一下程序:
开始必须引入这些头文件和一个静态库
#include <WinSock2.h>
#include <Windows.h>
#pragma comment(lib,"WS2_32")
因为程序中需要这些库的支持
//加载的套接字
WORD wvquest;
WSADATA WSAdata;
wvquest=MAKEWORD(2,2);
if (0!=WSAStartup(wvquest,(LPWSADATA)&WSAdata))
{
std::cout<<"加载套接字失败"<<std::endl;
}
加载套接字wvquest=MAKEWORD(2,2);使用了一个宏分别将2和2给WORD高字节和低字节赋初值。
//创建一个套接字
SOCKET m_socket =socket(AF_INET,SOCK_STREAM,0);
//绑定套接字
SOCKADDR_IN m_sockaddr;
m_sockaddr.sin_family=AF_INET;
m_sockaddr.sin_port=htons(3669);
m_sockaddr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
bind(m_socket,(sockaddr *)&m_sockaddr,sizeof(m_sockaddr));
这里要注意的是 对m_sockaddr;结构的一个初始化,
对这个结构的成员要注意的是.sin_port=htons(3669);是端口号 3669
//等待客户请求
SOCKADDR_IN clientsock;
int len= sizeof(SOCKADDR_IN);
SOCKET Client;
while(1)
{
Client=accept(m_socket,(SOCKADDR *)&clientsock,&len);
std::cout<<"客户端请求响应成功!"<<std::endl;
char s[256]={0};
recv(Client,s,256,0);
std::cout<<s<<std::endl;
closesocket(Client);
}
建立了种中链接后
开始接受请求并处理消息使用while 循环来使得不断的接受处理接收处理~~~
ID:Crazy迷恋