为初学者写的Winsock编程--一个简单的TCP服务器



介绍:
WinSock(Windows Sockets)API是一个微软的windows系统接口编程库。它最初是基于Berkeley sockets。但是微软做了一些相应的改动。这里我试图简单的介绍一下WinSock的编程技术,假定你已经开发过一些网络程序不论是什么操作系统。
如果你只有一台机器,不用担心,你仍然可以进行WinSock编程。你可以使用本地的地址localhost作为IP地址通常是127.0.0.1。如果你有你特TCP的服务器在机器上运行,还可以运行一个客户端程序在同一台电脑上。
简单的TCP服务器:
这里我要通过一个简单的TCP服务器向你介绍一下WinSock,我会一步一步讲。但在开始之前,你先要完成一点任务,然后在真正开始WinSock编程。
开始要用VC++ 6.0App Wizard建立一个 Win32的控制台程序。在这里选择support for MFC选项。
打开stdafx.h文件,添加#include <winsock2.h> 还有#include conio.h和iostream.h。使用Project-Settings-Link在其中的library modules list中添加ws2_32.lib。
以下是主程序:
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    int nRetCode = 0; 
 
    cout << "Press ESCAPE to terminate program/r/n";
    AfxBeginThread(ServerThread,0);
    while(_getch()!=27);
 
    return nRetCode;
}

主程序是用来建立一个线程然后循环调用_getch()。_getch()一直等待直到得到一个键盘输入的字符值。当得到ASCII值是27时返回,因为27的ASCII码是ESCAPE键。你也许知道即使我按了ESCAPE,开始建立的线程也不会结束。这根本不用担心。当main() 函数返回该线程将关闭同时我在开始建立的那个线程也会关闭。
服务器线程函数:
我要做的是列出服务器的线程,然后用注释解释每一行代码。首先TCP服务器是这样工作的。它侦听20248端口,这个可能凑巧和其它代码的冲突。当一个客户端连接时,服务器将返回一个信息到客户端给出IP地址然后开始在20248端口上接收数据。在控制台上同时打印一行连接的客户端的IP。当然你觉得写这么个程序毫无意义。你也许觉得它和windows系统中的SNDREC32.EXE程序一样没意义。如果这样我会觉得你太挑剔。
 CollapseUINT  ServerThread(LPVOID pParam)

    cout << "Starting up TCP server/r/n";

    //一个SOCKET定义,其实是unsigned int的typedef
    //在Unix系统中socket句柄也是这样的类型
    //因为这不可能在windows下从新定义类型所以一个统一的SOCKET类型被定义了
    SOCKET server;


    //WSADATA是一个在WSAStartup调用中填充数据的结构
    WSADATA wsaData;

    //sockaddr_in指定TCP/IP的socket地址。该协议的结构非常熟悉
    sockaddr_in local;

    //WSAStartup引入,第一个参数指定WinSock的版本,然后在程序中使用。
    int wsaret=WSAStartup(0x101,&wsaData);


    //WSAStartup在成功建立后返回0,如果不是就结束程序
    if(wsaret!=0)
    {
        return 0;
    }


    //现在非常熟悉的sockaddr_in结构参数
    local.sin_family=AF_INET; //Address family
    local.sin_addr.s_addr=INADDR_ANY; //Wild card IP address
    local.sin_port=htons((u_short)20248); //port to use


    //用socket函数建立SOCKET
    server=socket(AF_INET,SOCK_STREAM,0);


    //如果失败则退出程序
    if(server==INVALID_SOCKET)
    {
        return 0;
    }

    //将建立的SOCKET帮定到sockaddr_in
    if(bind(server,(sockaddr*)&local,sizeof(local))!=0)
    {
        return 0;
    }


    //开始侦听
    if(listen(server,10)!=0)
    {
        return 0;
    }


    //再建立接受已经连接的客户端的SOCKET
    SOCKET client;
    sockaddr_in from;
    int fromlen=sizeof(from);

    while(true)//we are looping endlessly
    {
        char temp[512];


        //当有数据时接受连接客户端
        client=accept(server,
            (struct sockaddr*)&from,&fromlen);
  
        sprintf(temp,"Your IP is %s/r/n",inet_ntoa(from.sin_addr));


        //向客户端发送一个字符串
        send(client,temp,strlen(temp),0);
        cout << "Connection from " << inet_ntoa(from.sin_addr) <<"/r/n";
  

        //关闭连接客户端的socket
        closesocket(client);

    }


    //关闭服务端socket
    closesocket(server);


    //通常调用WSACleanup来结束是比较安全的
    WSACleanup();

    return 0;
}


测试输出:
在服务端得到如下输出结果:
E:/work/Server/Debug>server
Press ESCAPE to terminate program
Starting up TCP server
Connection from 203.200.100.122
Connection from 127.0.0.1
E:/work/Server/Debug>


以下是客户段的输出结果:
nish@sumida:~$ telnet 202.89.211.88 20248
Trying 202.89.211.88...
Connected to 202.89.211.88.
Escape character is '^]'.
Your IP is 203.200.100.122
Connection closed by foreign host.
nish@sumida:~$


结束:
这样,你知道了怎样建立一个简单的TCP服务器了。如果更深一步我会介绍给你用 WinSock 建立更高级功能的程序。如果有人对该程序有疑问,请回复。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值