SDL_net_中文教程

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

SDL_net_中文教程
翻译来之wiki网站,翻译的有点烂。

黄建峰 2011年4月27日这个教程介绍如何在你的程序中使用SDL_net实现网络功能.在教程开始之前推荐您先了解下BSD Sockets。

使用 TCP
如果你需要一个可靠的但是有点慢的链接, TCP 符合你的需求: 此协议是面向连接的: 当你连接到一个主机,以及使用socket转换数据. 数据将无损的有序到达目的地. 在游戏中, 当你不需要很快的链接的时候TCP 是被用的最广泛的一个协议。

虽然这样,但是如果你需要数据有序的无损的到达目的地,TCP是你最好的选择(UDP不是最好的选择).
在这简单的 client-server 例子中,我们将做如下的事情:
服务端:
1.初始化SDL_net 库
2.设置监听的端口
3.打开一个socket绑定端口
4.接收连接
5.接受数据
6.对数据进行处理
7.清理,退出
客户端:
1.初始化SDL_net 库
2.解析服务器地址
3.打开一个socket
4.从用户出读取数据
5.发送数据
6.清理,退出
如果你有丰富的socket编程经验, 你会发现SDL_net是非常容易就可以上手的.
在接收到连接后, 我们将会得到关于主机的信息. 这是可选的,只是为了写本教程在这里稍微的提下.
还要注意的是服务器接收和管理的时候一次只能有一个连接,当然你可以使用这些技术来管理同时的多个连接(使用线程)。

代码:
这里是服务器代码:
#if 0
#!/bin/sh
gcc -Wall `sdl-config --cflags` tcps.c -o tcps `sdl-config --libs` -lSDL_net
exit
#endif
#include
#include
#include
#include "SDL_net.h"
int main(int argc, char **argv)
{
TCPsocket sd, csd; /* 定义服务端Socket ,客户端 socket */
IPaddress ip, *remoteIP; /* 定义本机ip ,客户端 ip */
int quit, quit2;
char buffer[512]; /* 接收数据缓存 */
if(SDLNet_Init() < 0)
{
fprintf(stderr, "SDLNet_Init: %s\n", SDLNet_GetError());
exit(EXIT_FAILURE);
}
/* 解析主机和端口,NULL为本机默认,端口2000 */
if(SDLNet_ResolveHost(&ip, NULL, 2000) < 0)
{
fprintf(stderr, "SDLNet_ResolveHost: %s\n", SDLNet_GetError());
exit(EXIT_FAILURE);
}
/* 打开一个TCP socket网络 (监听主机的端口) */
if(!(sd = SDLNet_TCP_Open(&ip)))
{
fprintf(stderr, "SDLNet_TCP_Open: %s\n", SDLNet_GetError());
exit(EXIT_FAILURE);
}
/* 等待连接,发送数据 */
quit = 0;
while(!quit)
{
/* 检查sd是否有新的链接.
* 如果有,接受,然后给链接打开一个新的socket
*/
if((csd = SDLNet_TCP_Accept(sd)))
{
/* 我们用 csd socket 连接到客户端
* sd 会被保留,等待下一个连接 */
/* 获取远程地址 */
if((remoteIP = SDLNet_TCP_GetPeerAddress(csd)))
/* 输出地址,和端口 */
printf("Host connected: %x %d\n",
SDLNet_Read32(&remoteIP->host),
SDLNet_Read16(&remoteIP->port));
else
fprintf(stderr,
"SDLNet_TCP_GetPeerAddress: %s\n", SDLNet_GetError());
quit2 = 0;
while(!quit2)
{
if(SDLNet_TCP_Recv(csd, buffer, 512) > 0)
{
printf("Client say: %s\n", buffer);
if(strcmp(buffer, "exit") == 0) /* 中断连接 */
{
quit2 = 1;
printf("T erminate connection\n");
}
if(strcmp(buffer, "quit") == 0) /* 退出程序 */
{
quit2 = 1;
quit = 1;
printf("Quit program\n");
}
}
}
/* 关闭客户端socket */
SDLNet_TCP_Close(csd);
}
SDLNet_TCP_Close(sd); /* 关闭服务端socket */
SDLNet_Quit();
return EXIT_SUCCESS;
}
这里是客户端的代码:
#if 0
#!/bin/sh
gcc -Wall `sdl-config --cflags` tcpc.c -o tcpc `sdl-config --libs`
-lSDL_net
exit
#endif
#include
#include
#include
#include "SDL_net.h"
int main(int argc, char **argv)
{
IPaddress ip; /* 服务器地址 */
TCPsocket sd; /* 定义服务器socket */
int quit, len;
char buffer[512];
/* 简单的参数检查 */
if(argc < 3)
{
fprintf(stderr, "Usage: %s host port\n", argv[0]);
exit(EXIT_FAILURE);
}
if(SDLNet_Init() < 0)
{
fprintf(stderr, "SDLNet_Init: %s\n", SDLNet_GetError());
exit(EXIT_FAILURE);
}
/* 解析主机 */
if(SDLNet_ResolveHost(&ip, argv[1], atoi(argv[2])) < 0)
fprintf(stderr, "SDLNet_ResolveHost: %s\n", SDLNet_GetError());
exit(EXIT_FAILURE);
}
/*打开一个TCP socket网络 (监听主机的端口) */
if(!(sd = SDLNet_TCP_Open(&ip)))
{
fprintf(stderr, "SDLNet_TCP_Open: %s\n", SDLNet_GetError()); exit(EXIT_FAILURE);
}
/* 发送信息 */
quit = 0;
while(!quit)
{
printf("Write something:\n>");
scanf("%s", buffer);
len = strlen(buffer) + 1;
if(SDLNet_TCP_Send(sd, (void *)buffer, len) < len)
{
fprintf(stderr, "SDLNet_TCP_Send: %s\n",
SDLNet_GetError());
exit(EXIT_FAILURE);
}
if(strcmp(buffer, "exit") == 0)
quit = 1;
if(strcmp(buffer, "quit") == 0)
quit = 1;
}
SDLNet_TCP_Close(sd);
SDLNet_Quit();
return EXIT_SUCCESS;
}
[edit]
使用UDP:
大部分的游戏使用UDP,因为UDP比TCP快. 但是速度快是有代价的: UDP无法提供一个可靠的方式发送数据到目的主机, 数据包也可能发生错误. UDP 是一个无链接协议, 这意味着
你不需要在本地和主机间建立一个连接, 但是你要将信息发送到一个特定的端口或者在一个端口上等待信息。

不管怎么说, SDL_net提供一个中间方法使用UDP进行连接:你能指定一个通道以及绑定一个远程主机到UDP socket. 用这种方式,你不需要每次都指定你要发送的数据包的地址。

服务端:
1.初始化SDL_net 库
2.在指定的端口打开一个socket
3.给数据包开辟内存
4.等待从客户端来的数据包
5.处理数据包
6.释放内存,退出
客户端:
1.初始化SDL_net 库
2.在一个随机的未使用的端口打开一个socket
3.解析服务端的地址
4.给数据包开辟内存
5.发送数据包
6.释放内存,退出
代码:
服务端代码:
#if 0
#!/bin/sh
gcc -Wall `sdl-config --cflags` udps.c -o udps `sdl-config --libs` -lSDL_net
exit
#endif
#include
#include
#include
#include "SDL_net.h"
int main(int argc, char **argv)
{
UDPsocket sd; /* 定义服务端 socket */
UDPpacket *p; /* 定义数据包 */
int quit;
/* 初始化 SDL_net */
if(SDLNet_Init() < 0)
{
fprintf(stderr, "SDLNet_Init: %s\n", SDLNet_GetError());
exit(EXIT_FAILURE);
}
/* 打开一个 socket 端口2000 */
if(!(sd = SDLNet_UDP_Open(2000)))
{
fprintf(stderr, "SDLNet_UDP_Open: %s\n", SDLNet_GetError());
exit(EXIT_FAILURE);
}
/* 给数据包开辟空间 */
if(!(p = SDLNet_AllocPacket(512)))
{
fprintf(stderr, "SDLNet_AllocPacket: %s\n", SDLNet_GetError());
exit(EXIT_FAILURE);
}
quit = 0;
while(!quit)
{
/* 等待数据包. 如果有数据UDP_Recv 返回值!= 0 */
if(SDLNet_UDP_Recv(sd, p))
{
printf("UDP Packet incoming\n");
printf("\t Chan: %d\n", p->channel);
printf("\t Data: %s\n", (char *)p->data);
printf("\t Len: %d\n", p->len);
printf("\t Maxlen: %d\n", p->maxlen);
printf("\t Status: %d\n", p->status);
printf("\t Address: %x %x\n", p->address.host,
p->address.port);
/* Quit if packet contains "quit" */
if(!strcmp((char *)p->data, "quit"))
quit = 1;
}
}
/* Clean and exit */
SDLNet_FreePacket(p);
SDLNet_Quit();
return EXIT_SUCCESS;
}
客户端:
#if 0
#!/bin/sh
gcc -Wall `sdl-config --cflags` udpc.c -o udpc `sdl-config --libs` -lSDL_net
exit
#endif
#include
#include
#include
#include "SDL_net.h"
int main(int argc, char **argv)
{
UDPsocket sd;
IPaddress srvadd;
UDPpacket *p;
int quit;
/* 检查参数 */
if(argc < 3)
{
fprintf(stderr, "Usage: %s host port\n", argv[0]);
exit(EXIT_FAILURE);
}
if(SDLNet_Init() < 0)
{
fprintf(stderr, "SDLNet_Init: %s\n", SDLNet_GetError());
exit(EXIT_FAILURE);
}
/* 打开一个随机的端口 */
if(!(sd = SDLNet_UDP_Open(0)))
{
fprintf(stderr, "SDLNet_UDP_Open: %s\n", SDLNet_GetError());
exit(EXIT_FAILURE);
}
/* 解析主机名 */
if(SDLNet_ResolveHost(&srvadd, argv[1], atoi(argv[2])))
{
fprintf(stderr, "SDLNet_ResolveHost(%s %d): %s\n", argv[1], atoi(argv[2]), SDLNet_GetError());
exit(EXIT_FAILURE);
}
if(!(p = SDLNet_AllocPacket(512)))
{
fprintf(stderr, "SDLNet_AllocPacket: %s\n", SDLNet_GetError());
exit(EXIT_FAILURE);
}
quit = 0;
while(!quit)
{
printf("Fill the buffer\n>");
scanf("%s", (char *)p->data);
p->address.host = srvadd.host; /* 设置主机地址 */
p->address.port = srvadd.port; /* 主机端口 */
p->len = strlen((char *)p->data) + 1;
SDLNet_UDP_Send(sd, -1, p); /* This sets the p->channel */ /* Quit if packet contains "quit" */
if(!strcmp((char *)p->data, "quit"))
quit = 1;
}
SDLNet_FreePacket(p);
SDLNet_Quit();
return EXIT_SUCCESS;
}
在这个例子中没有使用到通道,不过你可以在客户端来绑定通道,函数如下:
SDLNet_UDP_Bind(udpSocketDescriptor, channelNumber, &serverIPIddress)。

相关文档
最新文档