赞
踩
学习内容,参见《Windows网络编程》 第7章 Winsock基础
服务器/客户端连接模型见下图。
服务端流程
客户端流程
使用windows的Winsock 2编程,创建win32控制台工程,进行工程配置。
服务端代码,TCPServer.cpp。
- // TCPServer.cpp : Defines the entry point for the console application.
- //
-
- #include "stdafx.h"
- #include <WinSock2.h>
- #include <stdio.h>
- #include <stdlib.h>
-
- #define DEFAULT_PORT 5150
- #define DEFAULT_BUFFER 4096
-
- int iPort = DEFAULT_PORT;//Port to listen for clients on
- BOOL bInterface = FALSE;//Listen on the specified interface
- BOOL bRecvOnly = FALSE;//Receive data only; don't echo back
- TCHAR szAddress[128];//Interface to listen for clients on
-
- //Print usage information and exit
- void usage()
- {
- printf("usage:server[-p:x][-i:IP][-o]\n\n");
- printf(" -p:x Port number to listen on\n");
- printf(" -i:str Interface to listen on\n");
- printf(" -o Don't echo the data back\n\n");
-
- ExitProcess(1);
- }
-
- //Parse the command line arguments, and set some global flags
- //to indicate what actions to perform
- void ValidateArgs(int agrc, _TCHAR** argv)
- {
- for (int i = 1; i < agrc; i++)
- {
- if ((argv[i][0] == _T('-')) || (argv[i][0] == _T('/')))
- {
- switch (tolower(argv[i][1]))
- {
- case _T('p'):
- iPort = _ttoi(&argv[i][3]);
- break;
- case _T('i'):
- bInterface = TRUE;
- if (_tcslen(argv[i]) > 3)
- {
- _tcscpy_s(szAddress, &argv[i][3]);
- }
- break;
- case _T('o'):
- //只接受数据
- bRecvOnly = TRUE;
- break;
- default:
- usage();
- break;
- }
- }
- }
- }
-
- DWORD WINAPI ClientThread(LPVOID lpParam)
- {
- SOCKET sock = (SOCKET)lpParam;
- char szBuff[DEFAULT_BUFFER];
-
- while (true)
- {
- //Perform a blocking recv() call
- int ret = recv(sock, szBuff, DEFAULT_BUFFER, 0);
- if (0 == ret)
- {
- break;
- }
- else if (SOCKET_ERROR == ret)
- {
- printf("recv() failed:%d\n", WSAGetLastError());
- break;
- }
- szBuff[ret] = '\0';
- printf("RECV:'%s'\n", szBuff);
-
- //if we selected to echo the data back, do it
- if (!bRecvOnly)
- {
- int nLeft = ret;
- int idx = 0;
-
- //make sure we write all the data
- while (nLeft > 0)
- {
- ret = send(sock, &szBuff[idx], nLeft, 0);
- if (0 == ret)
- {
- break;
- }
- else if (SOCKET_ERROR == ret)
- {
- printf("send() failed:%d\n", WSAGetLastError());
- break;
- }
- nLeft -= ret;
- idx += ret;
- }
- }
- }
-
- return 0;
- }
-
- int _tmain(int argc, _TCHAR* argv[])
- {
- ValidateArgs(argc, argv);
-
- WSADATA wsd;
- if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
- {
- printf("Failed to load Winsock!\n");
- return 1;
- }
-
- //Create our listening socket
- SOCKET sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
- if (sListen == SOCKET_ERROR)
- {
- printf("socket() failed:%d\n", WSAGetLastError());
- return 1;
- }
-
- //Select the local interface, and bind to it
- struct sockaddr_in local;
- if (bInterface)
- {
- local.sin_addr.s_addr = inet_addr(szAddress);
- if (local.sin_addr.s_addr == INADDR_NONE)
- {
- usage();
- }
- }
- else
- {
- //INADDR_ANY是所有网卡地址
- local.sin_addr.s_addr = htonl(INADDR_ANY);
- }
- local.sin_family = AF_INET;
- local.sin_port = htons(iPort);
-
- //绑定监听网卡地址和端口
- if (bind(sListen, (struct sockaddr*)&local, sizeof(local)) == SOCKET_ERROR)
- {
- printf("bind() failed:%d\n", WSAGetLastError());
- }
- //开始监听客户端
- listen(sListen, 8);
-
- printf("begin accept on port:%d\n", iPort);
-
- //In a continuous loop, wait for incoming clients.Once one
- //is detected, create a thread and pass the handle off to it
- while (true)
- {
- struct sockaddr_in client;
- int iAddrSize = sizeof(client);
- SOCKET sClient = accept(sListen, (struct sockaddr*)&client, &iAddrSize);
- if (sClient == INVALID_SOCKET)
- {
- printf("accept() failed:%d\n", WSAGetLastError());
- break;
- }
- printf("Accepted client:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
-
- DWORD dwThreadId;
- HANDLE hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)sClient,
- 0, &dwThreadId);
- if (hThread == NULL)
- {
- printf("CreateThread() failed:%d\n", GetLastError());
- break;
- }
- CloseHandle(hThread);
- }
- closesocket(sListen);
-
- WSACleanup();
-
- return 0;
- }
客户端代码,TCPClient.cpp。
- // TCPClient.cpp : Defines the entry point for the console application.
- //
-
- #include "stdafx.h"
- #include <WinSock2.h>
- #include <stdio.h>
- #include <stdlib.h>
-
- #define DEFAULT_COUNT 5
- #define DEFAULT_PORT 5150
- #define DEFAULT_BUFFER 2048
- #define DEFAULT_MESSAGE _T("This is a test of the emergency broadcasting system")
-
- TCHAR szServer[128];
- TCHAR szMessage[1024];
-
- int iPort = DEFAULT_PORT;
- DWORD dwCount = DEFAULT_COUNT;
- BOOL bSendOnly = FALSE;
-
- //Print usage information and exit
- void usage()
- {
- printf("usage:client[-p:x][-s:IP][-n:x][-o]\n\n");
- printf(" -p:x Remote port to send to \n");
- printf(" -s:IP Server's IP address or host name\n");
- printf(" -n:x Number of times to send message\n");
- printf(" -o Send messages only; don't receive\n");
-
- ExitProcess(1);
- }
-
- //Parse the command line arguments, and set some global flags
- //to indicate what actions to perform
- void ValidateArgs(int argc, _TCHAR** argv)
- {
- for (int i = 1; i < argc; i++)
- {
- if ((argv[i][0] == _T('-')) || (argv[i][0] == _T('/')))
- {
- switch (tolower(argv[i][1]))
- {
- case _T('p'):
- if (_tcslen(argv[i]) > 3)
- {
- iPort = _ttoi(&argv[i][3]);
- }
- break;
- case _T('s'):
- if (_tcslen(argv[i]) > 3)
- {
- _tcscpy_s(szServer, &argv[i][3]);
- }
- break;
- case _T('n'):
- if (_tcslen(argv[i]) > 3)
- {
- dwCount = _ttol(&argv[i][3]);
- }
- break;
- case _T('o'):
- bSendOnly = TRUE;
- break;
- default:
- usage();
- break;
- }
- }
- }
- }
-
- int _tmain(int argc, _TCHAR* argv[])
- {
- ValidateArgs(argc, argv);
-
- WSADATA wsd;
- if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
- {
- printf("Failed to load Winsock library!\n");
- return 1;
- }
-
- _tcscpy_s(szMessage, DEFAULT_MESSAGE);
-
- //Create the socket, and attempt to connect to the server
- SOCKET sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
- if (sClient == INVALID_SOCKET)
- {
- printf("socket() failed:%d\n", WSAGetLastError());
- return 1;
- }
-
- struct sockaddr_in server;
- server.sin_family = AF_INET;
- server.sin_port = htons(iPort);
-
- //If the supplied server address wasn't in the form
- //"aaa.bbb.ccc.ddd,"it's a host name, so try to resolve it
- int nServerLen = (int)_tcslen(szServer);
- if (0 == nServerLen)
- {
- struct hostent* host = gethostbyname(szServer);
- if (host == NULL)
- {
- printf("Unable to resolve server:%s\n", szServer);
- return 1;
- }
-
- CopyMemory(&server.sin_addr, host->h_addr_list[0], host->h_length);
- }
- else
- {
- server.sin_addr.s_addr = inet_addr(szServer);
- }
-
- if (connect(sClient, (struct sockaddr*)&server, sizeof(server))
- == SOCKET_ERROR)
- {
- printf("connect() failed:%d\n", WSAGetLastError());
- return 1;
- }
-
- //Send and receive data
- char szBuffer[DEFAULT_BUFFER];
- int ret = 0;
-
- for (int i = 0; i < (int)dwCount; i++)
- {
- ret = send(sClient, szMessage, (int)_tcslen(szMessage), 0);
- if (ret == 0)
- {
- break;
- }
- else if (ret == SOCKET_ERROR)
- {
- printf("send() failed:%d\n", WSAGetLastError());
- break;
- }
-
- printf("Send %d bytes\n", ret);
- if (!bSendOnly)
- {
- ret = recv(sClient, szBuffer, DEFAULT_BUFFER, 0);
- if (ret == 0)
- {
- break;
- }
- else if (ret == SOCKET_ERROR)
- {
- printf("recv() failed:%d\n", WSAGetLastError());
- break;
- }
-
- szBuffer[ret] = _T('\0');
- printf("RECV [%d bytes]:'%s'\n", ret, szBuffer);
- }
- }
- closesocket(sClient);
-
- WSACleanup();
-
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。