鱼C论坛

 找回密码
 立即注册

【原创】socket编程服务端的编写

热度 4已有 2249 次阅读2013-8-16 10:55 |个人分类:C\C++

     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迷恋

路过

鸡蛋

鲜花
4

握手

雷人

刚表态过的朋友 (4 人)

发表评论 评论 (7 个评论)

回复 格式天下 2013-8-16 16:30
我了个去,楼主,你这些东西在哪学的,我也想学,好牛逼的样子额
回复 Crazy迷恋. 2013-8-16 17:10
格式天下: 我了个去,楼主,你这些东西在哪学的,我也想学,好牛逼的样子额
没事瞎琢磨来着~~不过朋友有兴趣研究可以购买书籍VC++网络编程一书。出视频的有棉猴的网络编程VC驿站的免费教程。我在看VC驿站的视频。其他的......清晰地不够不想看~~~其实坐等python也行。甲鱼会把它讲好的。居说他跟它以经亲密接触了呢~~~~
回复 格式天下 2013-8-16 17:19
够详细!!!,谢谢楼主啦,很久就想学这玩意,就是不知道在哪学
回复 小甲鱼 2013-8-17 20:17
牡丹是坏人~~~~
回复 Crazy迷恋. 2013-8-17 22:24
小甲鱼: 牡丹是坏人~~~~
鱼c第一坏
回复 Crazy迷恋. 2013-8-17 22:24
小甲鱼: 牡丹是坏人~~~~
回复 wmslecz 2013-8-18 09:05
迷恋太牛B了哈.

facelist

您需要登录后才可以评论 登录 | 立即注册

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-18 19:51

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

返回顶部