楼上已经把如何建立socket说明了,我只讲一下数据封装和传输过程:
1、UDP 137服务已经启动,并且会回应接受的数据包;
2、发送端的应用准备发送的数据;
3、调用socket,指明目标地址和端口(137),源地址和端口可以指定,也可以忽略;
4、socket封装UDP包,增加UDP包头,进而封装IP包,增加IP包头;
5、socket调用底层驱动(链路层),将IP包封装成物理链路上传输的帧,以以太网为例,会增加帧头,包括源MAC和目标MAC,当然中间会用到ARP,解析出IP和MAC的对应关系,由协议栈完成,应用可以不必理会;
6、底层的数据帧通过物理链路传输到对方;
7、对方接收后,反过来从底层向上层,逐渐剥去帧头、IP头、UDP头,得到实际的数据,并根据UDP头部的目标端口,传送给上层的应用,137端口服务;
8、137端口服务处理后,反后头来,发送回应数据,发送过程同上。
不会也是考网络编程吧?我们刚刚考好,刚复习完
我也是略懂
其实楼主还有一个没提到,就是 winsockdll
楼主说的afxsockh我倒是不怎么了解
其他的,他们间是这样的
所有的h是头文件,lib是静态库文件,dll是动态库文件
之所以楼主能使用这些编程就是考这些分工严密的东东帮忙。
socket编程说到底就是使用网络的编程,和普通的程序不同,
socket要用到网络,那它就得用网络设备(就是网卡)。
但一般我们用来写程序的都是像c++这类高级语言,是不 *** 作底层硬件的。
所以就需要有人来帮我们完成或者说屏蔽掉底层的 *** 作。
大致流程是,首先,网卡会有驱动程序来驱动,一般是在系统内的sys文件完成,
然后dll会接管工作,此时都还是些硬件的 *** 作,但通过动态链接库后,很多底层的细节开始被屏蔽,这里只指一些琐碎的 *** 作dll会帮你完成掉了,但其实dll完成的也是个半成品,楼主也没办法直接用来编程。
于是lib上场了,lib将dll处理的半成品拿来,将它们封装成一个个API,这样,我们就可以通过API来调用网卡的功能了,当然这还不够,API毕竟也是个很麻烦的东西,而且功能不够细化。
于是就做了h,这些头文件是可以直接打开来看的,实际里面就是些调用API的命令,还有就是把和相关的业务逻辑的变量啊结构体啊给定义一下。
比如在winsockh中会定义sockaddr_in这样的结构体,用它来表示一个主机的IP和端口很方便,不过也不复杂,楼主也当然可以定义自己的结构体,不过,正是因为这些头文件帮你定义好了很多业务中常用的变量结构体之类,使得你编程的时候能更加关心程序本身了。
大致关系就是这样子调用的。
在写程序中,头文件的包含是不能少的,静态库也必须放到程序里,当然可以通过开发环境的添加或者在程序中直接包含都行,动态链接库一般不用 *** 心,会自带的,不过有时也会遇到损坏之类的,网上直接下一个就行了。
具体的winsockh winsock2h也就是些版本上的区别,就像QQ2009和QQ2010都是QQ,都能聊天,就是版本更新了,很多细小的地方有些变动而已。
我用C++ socket写过点东西,c# socket也用过。其实呢,却别不是太大。c++ socket 程序的流程: 服务端都是建立套接字、绑定套接字、设置套接字为监听状态、接受客户端的连接请求、和客户端通信。 客户端则是,创建套接字,设置服务器端的地址、端口号,连接服务器、和服务器通信。当然,这只是最简单的,还有各种的模型,阻塞、非阻塞、异步、非异步的。 而c#,也可以按照这个流程来写,甚至连调用函数的名称都没变。但是,C# 对socket进行了些封装。晕,这个封装写起来就麻烦了。推荐本书吧《c# 网络编程实例》 讲的还是不错的,既有基础知识的讲解,也有实例。要资料的话,留个邮箱。。。。。
是要MFC还是application?
给你个application的吧 要用MFC可以发我消息
服务器端:
#include <stdioh>
#include <Winsock2h>
#pragma comment(lib, "ws2_32lib")
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return;
}
if ( LOBYTE( wsaDatawVersion ) != 1 ||
HIBYTE( wsaDatawVersion ) != 1 ) {
WSACleanup( );
return;
}
SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN addrSrv;
addrSrvsin_addrS_unS_addr=htonl(INADDR_ANY);
addrSrvsin_family=AF_INET;
addrSrvsin_port=htons(6000);
bind(sockSrv,(SOCKADDR)&addrSrv,sizeof(SOCKADDR));// 绑定端口
listen(sockSrv,5);
SOCKADDR_IN addrClient;// 连接上的客户端ip地址
int len=sizeof(SOCKADDR);
while(1)
{
SOCKET sockConn=accept(sockSrv,(SOCKADDR)&addrClient,&len);// 接受客户端连接,获取客户端的ip地址
char sendBuf[50];
sprintf(sendBuf,"Welcome %s to here!",inet_ntoa(addrClientsin_addr));// 组合消息发送出去
send(sockConn,sendBuf,strlen(sendBuf)+1,0);// 发送消息到客户端
char recvBuf[50];
recv(sockConn,recvBuf,50,0);// 接受客户端消息
printf("%s\n",recvBuf);
//closesocket(sockConn);//断开连接
}
}
客户端代码
#include <stdioh>
#include <Winsock2h>
#pragma comment(lib, "ws2_32lib")
void main()
{
WORD wVersionRequested;
WSADATA wsaData;//WSAata用来存储系统传回的关于WinSocket的资料。
int err;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return;
}
if ( LOBYTE( wsaDatawVersion ) != 1 ||HIBYTE( wsaDatawVersion ) != 1 )
{
WSACleanup( );
return;
}
SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);// AF_INET tcp连接
//初始化连接与端口号
SOCKADDR_IN addrSrv;
addrSrvsin_addrS_unS_addr=inet_addr("127001");//本机地址,服务器在本机开启
addrSrvsin_family=AF_INET;
addrSrvsin_port=htons(6000);// 设置端口号
connect(sockClient,(SOCKADDR)&addrSrv,sizeof(SOCKADDR));//连接服务器
char recvBuf[50];
recv(sockClient,recvBuf,50,0);//接受数据
printf("%s\n",recvBuf);
send(sockClient,"hello",strlen("hello")+1,0);//发送数据
closesocket(sockClient);//关闭连接
WSACleanup();
}
注意端口号不要设置保留端口和3000不然会出错
这是一个通信协议的问题
一个比较简单的方案,效率和灵活性都有些问题,仅供参考:
一个固定的结构体,加一段变长的数据
struct xxx {
int magic_number;
int serial_number;
int command_type;
int content_length;
}
变长数据 content 的结构是这样的:
<key_len><key><value_len><value>
key_len是一个int, key的长度由key_len指定
value_len是一个int, value的长度由value_len指定
content 直接在结构体后面发出,由content_length指定长度
发送总长是 sizeof(xxx) + xxxcontent_length
接收方接收 sizeof(xxx) 字节到一个 xxx 里面以后,验证合法性,再接收 content_length 字节就行了
接收到content之后逐项解析 (key, value) 对,获取数据
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)