Winsock 编程入门 - 简单 TCP 服务器






4.93/5 (118投票s)
2002年2月26日
3分钟阅读

953924

4
WinSock编程的介绍。解释了一个简单的TCP服务器。
引言
WinSock(Windows Sockets)API 是 Microsoft Windows 操作系统的一个 socket 编程库。它最初基于 Berkeley sockets。但是采用了一些 Microsoft 特定的更改。在本文中,我将尝试向您介绍使用 WinSock 进行 socket 编程,假设您从未在任何操作系统上进行过任何类型的网络编程。
如果您只有一台机器,请不要担心。您仍然可以编写 WinSock 程序。您可以使用本地环回地址,称为 localhost,IP 地址为 127.0.0.1。因此,如果您在您的机器上运行一个 TCP 服务器,运行在同一机器上的客户端程序可以使用这个环回地址连接到服务器。
简单的 TCP 服务器
在本文中,我将通过一个简单的 TCP 服务器向您介绍 WinSock,我们将逐步创建它。但在我们开始之前,您必须做一些事情,以便我们真正准备好开始我们的 WinSock 程序
- 最初,使用 VC++ 6.0 App Wizard 创建一个 Win32 控制台应用程序。
- 记住设置选项来添加对 MFC 的支持
- 打开文件stdafx.h并添加以下行:-
#include <winsock2.h>
- 同时在 winsock2.h 之后
#include
conio.h 和 iostream - 选择“项目-设置-链接”并将 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; }
我们在 main()
中所做的是启动一个线程,然后循环调用 _getch()
。_getch()
只是等待直到按下按键,并返回读取的字符的 ASCII 值。我们循环直到返回值为 27,因为 27 是 ESCAPE 键的 ASCII 码。您可能想知道,即使我们按下 ESCAPE,我们启动的线程仍然会处于活动状态。完全不用担心。当 main()
返回时,进程将终止,并且我们的主线程启动的线程也会被突然终止。
ServerThread 函数
现在我将列出我们的 ServerThread
函数,并使用代码注释来解释每行相关代码的作用。基本上,我们的 TCP 服务器所做的是这样。它在端口 20248 上监听,这恰好也是我的 Code Project 会员 ID。真是巧合。当客户端连接时,服务器会将包含其 IP 地址的消息发送回客户端,然后关闭连接并返回到端口 20248 上接受连接。它还会在运行的控制台上打印一行消息,表明有来自该特定 IP 地址的连接。总而言之,一个绝对无用的程序,您可能会这么想。事实上,你们中的一些人甚至可能认为这和 Windows 自带的 SNDREC32.EXE 一样无用。我说那些人真残忍。
UINT ServerThread(LPVOID pParam) { cout << "Starting up TCP server\r\n"; //A SOCKET is simply a typedef for an unsigned int. //In Unix, socket handles were just about same as file //handles which were again unsigned ints. //Since this cannot be entirely true under Windows //a new data type called SOCKET was defined. SOCKET server; //WSADATA is a struct that is filled up by the call //to WSAStartup WSADATA wsaData; //The sockaddr_in specifies the address of the socket //for TCP/IP sockets. Other protocols use similar structures. sockaddr_in local; //WSAStartup initializes the program for calling WinSock. //The first parameter specifies the highest version of the //WinSock specification, the program is allowed to use. int wsaret=WSAStartup(0x101,&wsaData); //WSAStartup returns zero on success. //If it fails we exit. if(wsaret!=0) { return 0; } //Now we populate the sockaddr_in structure 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 //the socket function creates our SOCKET server=socket(AF_INET,SOCK_STREAM,0); //If the socket() function fails we exit if(server==INVALID_SOCKET) { return 0; } //bind links the socket we just created with the sockaddr_in //structure. Basically it connects the socket with //the local address and a specified port. //If it returns non-zero quit, as this indicates error if(bind(server,(sockaddr*)&local,sizeof(local))!=0) { return 0; } //listen instructs the socket to listen for incoming //connections from clients. The second arg is the backlog if(listen(server,10)!=0) { return 0; } //we will need variables to hold the client socket. //thus we declare them here. SOCKET client; sockaddr_in from; int fromlen=sizeof(from); while(true)//we are looping endlessly { char temp[512]; //accept() will accept an incoming //client connection client=accept(server, (struct sockaddr*)&from,&fromlen); sprintf(temp,"Your IP is %s\r\n",inet_ntoa(from.sin_addr)); //we simply send this string to the client send(client,temp,strlen(temp),0); cout << "Connection from " << inet_ntoa(from.sin_addr) <<"\r\n"; //close the client socket closesocket(client); } //closesocket() closes the socket and releases the socket descriptor closesocket(server); //originally this function probably had some use //currently this is just for backward compatibility //but it is safer to call it as I still believe some //implementations use this to terminate use of WS2_32.DLL WSACleanup(); return 0; }
测试
运行服务器并使用 telnet 连接到服务器运行的机器的端口 20248。如果您在同一台机器上运行,则连接到 localhost。
示例输出
我们在服务器上看到这个输出
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 完成的事情,包括创建一个合适的 TCP 客户端等等。如果有人在编译代码时遇到问题,请给我发邮件,我会给您发送一个压缩的项目。谢谢。