#define VERSION_MAJOR      2
#define VERSION_MINOR      0
#define UM_SOCK                          WM_USER+100
#define MAX_ERROR_TEXT 64
#define BUFFER_LENGTH      1024
#define ServerName                            "127.0.0.1"
#define UserPort                             6666
/*客户程序
我在Project-》settings-》link-》Object/library modules 中加入了 WS2_32.LIB WSOCK32.LIB 但是连接是出现
Compiling...
client.cpp
Linking...
LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Debug/client.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
*/#ifndef _WINSOCKAPI_
#define _WINSOCKAPI_   /* Prevent inclusion of winsock.h in windows.h */
#endif#include <windows.h>
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>SOCKET   Sockets;         // 套接字描述符
HWND         GlobalhWindow;
char    EchoClassStr[] = "WS2EchoClient"; 
char         sbuf[BUFFER_LENGTH], rbuf[BUFFER_LENGTH];     // 发送/接收缓冲区
DWORD         TotalByteSent;                // 总的发送字节数
WSABUF  SendBuf, RecvBuf;         // 发送/接收缓冲区结构BOOL InitWindow(HINSTANCE InstanceHandle,HINSTANCE PrevInstanceHandle);
void  DisplayInfo(HWND hWnd, WSABUF * lpBuffer);
void CALLBACK SendCompFunc( DWORD Error, DWORD    BytesTransferred, LPWSAOVERLAPPED Overlapped, DWORD   Flags);
int DoOverlappedCallbackSend(SOCKET Socket,LPWSABUF  Buffers);
int DoRecv(SOCKET Socket, LPWSABUF lpRecvBuffer);
BOOL MakeConnection(void);
BOOL InitWS2(void);
LRESULT CALLBACK MainWndProc(HWND   WindowHandle,UINT   Message,WPARAM WParam,LPARAM LParam);
int APIENTRY WinMain(HINSTANCE InstanceHandle,
    HINSTANCE PrevInstanceHandle,
    LPSTR  CmdLine,
    int    CmdShow)
{
    MSG      Message;      
    if (!InitWindow(InstanceHandle, PrevInstanceHandle)) {
        MessageBox(NULL, "Couldn't Initialize Echo!", "Error",
                            MB_OK | MB_ICONSTOP | MB_SETFOREGROUND);
                  return(0);
    }
    GlobalhWindow = CreateWindow(EchoClassStr, "WinSock 2 Echo Client",
                  WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                  CW_USEDEFAULT, NULL, NULL, InstanceHandle, NULL);
    if (GlobalhWindow == NULL) {
            MessageBox(NULL, "CreateWindow()!", "Error", MB_OK | MB_ICONSTOP | MB_SETFOREGROUND);
            return(0);
    }
    if (!InitWS2()) // 启动WinSock 2.
                  return(0);
    if (!MakeConnection()) // 与服务器建立连接
                  return(0);
    ShowWindow(GlobalhWindow, CmdShow);
    UpdateWindow(GlobalhWindow);
    while (GetMessage(&Message, NULL, 0, 0)) {
        TranslateMessage(&Message);
        DispatchMessage(&Message);
    }
    WSACleanup();  // 收到WM_QUIT消息后,结束WinSock 2.
    return(Message.wParam);
} // WinMain()LRESULT CALLBACK MainWndProc(
     HWND   WindowHandle,
     UINT   Message,
     WPARAM WParam,
     LPARAM LParam)
{
         int retcode;
         char MsgText[128];
    switch (Message) {
                   case UM_SOCK:
                            switch (LParam) {
                                     case FD_CONNECT:         //连接建立完成,置标志。
                                              WSAAsyncSelect(Sockets, GlobalhWindow, UM_SOCK, FD_READ);
                                               break;
                                     case FD_READ:         //数据读准备好,接收网络数据。
                                               retcode = DoRecv(Sockets, &RecvBuf);
                                               if (retcode == 1) 
                                                        DisplayInfo(WindowHandle, &RecvBuf);
                                               break;
                                     case FD_WRITE: //写准备好,发送数据。
                                               retcode = DoOverlappedCallbackSend(Sockets, &SendBuf);
                                              SendBuf.len = 0;
                             break;
                                     case FD_CLOSE:       //连接关闭。
                                            closesocket(Sockets);
                                         break;
                              default:
                                           if (WSAGETSELECTERROR(LParam) != 0) {
                                                        sprintf(MsgText, "Client: LParam=%d",WSAGETSELECTERROR(LParam));
                                                        MessageBox(GlobalhWindow, MsgText,
                                                                  "Error", MB_OK | MB_ICONSTOP | MB_SETFOREGROUND);
                                                      closesocket(Sockets);
                                               }
                                                  break;
                            }
                            break;
             case WM_CHAR:
                     if (WParam == 0x0d) // 用户键入回车键则发送一行。
                               PostMessage(GlobalhWindow, UM_SOCK, (WPARAM) WParam, (LPARAM)FD_WRITE);
                            else 
                                     SendBuf.buf[SendBuf.len++] = (char)WParam;
                     break;
                   case WM_DESTROY:         // 关闭监听套接字并退出应用程序
                            closesocket(Sockets);
                            PostQuitMessage(0);
                            break;
                   default:
                            return (DefWindowProc(WindowHandle, Message, WParam, LParam));
         } // switch(Message)
         return (0);
} // MainWndProc()
 /* * 启动WinSock 2,协商WinSock版本号,初始化接收发送缓冲区。 * 成功返回TRUE,失败返回FALSE。 */BOOL InitWS2(void)
{
    int           Error;              // catches return value of WSAStartup
    WORD          VersionRequested;   // passed to WSAStartup
    WSADATA       WsaData;            // receives data from WSAStartup
    BOOL          ReturnValue = TRUE; // return value
VersionRequested = MAKEWORD(VERSION_MAJOR, VERSION_MINOR);
    Error = WSAStartup(VersionRequested, &WsaData); // 启动WinSock 2
    if (Error) {
        MessageBox(GlobalhWindow, "Could not find high enough version of WinSock",
                            "Error", MB_OK | MB_ICONSTOP | MB_SETFOREGROUND);
        ReturnValue = FALSE;
    } else {// 确认WinSock 2 DLL支持我们需要的精确版本号,否则,调用WSACleanup()。
        if (LOBYTE(WsaData.wVersion) != VERSION_MAJOR 
                           || HIBYTE(WsaData.wVersion) != VERSION_MINOR) {
            MessageBox(GlobalhWindow, "Could not find the correct version of WinSock",
                                     "Error",  MB_OK | MB_ICONSTOP | MB_SETFOREGROUND);
            WSACleanup();
            ReturnValue = FALSE;
        }
    }
         SendBuf.len = RecvBuf.len = 0; // 初始化接收/发送缓冲区。
         SendBuf.buf = sbuf;
         RecvBuf.buf = rbuf;
    return(ReturnValue);
} // InitWS2()

解决方案 »

  1.   

    /* * 和服务器建立连接。成功返回TRUE,失败返回FALSE。 */
    BOOL MakeConnection(void)
    {
        int             ConnectStatus;    // the return value of WSAConnect
        int             Error;            // gets error values
        BOOL            ReturnValue;      // holds the return value
        struct sockaddr_in SockAddr;      // socket address for WSAConnect
        int             SockAddrLen;      // the length of the above
        CHAR MsgText[MAX_ERROR_TEXT];
        Sockets = WSASocket(PF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
        if (Sockets == INVALID_SOCKET) {
            sprintf(MsgText, "Could not open a socket. [%d]", WSAGetLastError());
            MessageBox(GlobalhWindow, MsgText, "Non-fatal error.", MB_OK | MB_SETFOREGROUND);
            return(FALSE);
        }
             WSAAsyncSelect(Sockets, GlobalhWindow, UM_SOCK, FD_CONNECT); // 设置连接建立的事件通知
        SockAddr.sin_family = AF_INET;
        SockAddr.sin_port = htons(UserPort);
        SockAddr.sin_addr.s_addr = inet_addr(ServerName);
        SockAddrLen = sizeof(SockAddr);
             // 和远程服务器建立连接。
              ConnectStatus = WSAConnect(Sockets, (struct sockaddr *)&SockAddr, SockAddrLen, 
                      NULL, NULL, NULL, NULL);
        if (ConnectStatus == SOCKET_ERROR) {
            Error = WSAGetLastError();
            if (Error != WSAEWOULDBLOCK) { // 错误WSAEWOULDBLOCK意味着连接稍后建立
                wsprintf(MsgText, "WSAConnect failed.  Error code: %d", Error);
                MessageBox(GlobalhWindow, MsgText, "Error", 
                                        MB_OK | MB_ICONSTOP | MB_SETFOREGROUND);
                ReturnValue = FALSE;
            }
        } 
             return(ReturnValue);
    } // MakeConnection()
    /*
     * 接收数据。
     */
    int DoRecv(SOCKET Socket, LPWSABUF lpRecvBuffer)
    {
        DWORD  NumBytes;         // stores how many bytes we received
        int    Error;                   // gets error values
        int    Result;                   // gets return value from WSARecv
        DWORD  Flags=0;              // flags for WSARecv
        int    ReturnValue = 1;          // returnValue
        lpRecvBuffer->len = BUFFER_LENGTH - 1;
        Result = WSARecv(Socket, lpRecvBuffer, 1, &NumBytes, &Flags, NULL, NULL); // 接收数据
        if (Result == SOCKET_ERROR) {
            Error = WSAGetLastError();
            switch (Error) {
                                case WSAENETRESET:  
                                case WSAECONNRESET:
                                         ReturnValue = -1;  // 连接被重置
                                         break;
                                case WSAEWOULDBLOCK:         // 没有数据可供读取
                                         ReturnValue = 0;
                                         break;
                                default:       // 其它错误
                                         ReturnValue = -2;
                                         break;
            }
        }
            lpRecvBuffer->len = NumBytes;
        return(ReturnValue);
    } // DoRecv()
    /*
     * 使用回调函数的重叠发送方式发送数据。
     */
    int DoOverlappedCallbackSend(
             SOCKET Socket,
        LPWSABUF  Buffers)    
    {
        int             Size = 0;      // how many bytes we send
        int             Error;         // return value of WSASend
        int             Errno;         // result of WSAGetLastError
        DWORD           BytesSent;     // needed in WSASend
        int             ReturnValue = 1;   // the return value
        WSAOVERLAPPED         Overlapped;
        // 发送数据。完成例程设置为函数SendCompFunc()。
             Error = WSASend(Socket, Buffers, 1, &BytesSent, 0, &Overlapped, SendCompFunc);
        if (Error == SOCKET_ERROR) {
            Errno = WSAGetLastError();
            if (Errno == WSAEWOULDBLOCK)  
                         // WSAEWOULDBLOCK意味着必须等待FD_WRITE事件才能发送
                ReturnValue = 0;
            else if (Errno == WSA_IO_PENDING)  // 重叠操作成功初始化
                ReturnValue = 1;
            else // 其它错误
                ReturnValue = -1;
        }
        // 如果没有错误,意味着发送操作立即完成。
        return(ReturnValue);
    } // DoOverlappedCallbackSend()
    /*
     * 完成例程在已成功初始化的重叠操作完成时被调用。它用来统计发送的字节数。
     * 参数:
     *   Error -- 提供重叠操作的完成状态。
     *   BytesTransferred -- 提供实际发送的字节数。
     *   Overlapped -- 提供一个指向WSAOVERLAPPED结构的指针,其hEvent域可以用来
     *            给完成例程传递上下文信息。
     *   Flags -- 未用。
     */
    void CALLBACK SendCompFunc(
         DWORD           Error,
         DWORD           BytesTransferred,
         LPWSAOVERLAPPED Overlapped,
         DWORD           Flags)
    {
             TotalByteSent += BytesTransferred; // 统计发送字节数。
             if (Error) 
            MessageBox(NULL, "Error during overlapped send.", "Error", MB_OK | MB_SETFOREGROUND);
    } // SendCompFunc()
    void  DisplayInfo(HWND hWnd, WSABUF * lpBuffer)//显示接收数据子程序。
    {
          HDC dc;
          int  l;
        char line[128];
        static int row = 0;
             lpBuffer->buf[lpBuffer->len] = 0;
             if (dc = GetDC(hWnd)) {
                l = wsprintf((LPSTR) line, "%s",lpBuffer->buf);
                   TextOut(dc, 10, 16*row, (LPSTR) line, lpBuffer->len);
            ReleaseDC(hWnd, dc);
          }
          row ++;
    }BOOL InitWindow(
         HINSTANCE InstanceHandle,
         HINSTANCE PrevInstanceHandle)
    {
        WNDCLASS WndClass;           // window class structure
        if (!PrevInstanceHandle) {
            WndClass.style         = CS_HREDRAW | CS_VREDRAW;
            WndClass.lpfnWndProc   = MainWndProc;
            WndClass.cbClsExtra    = 0;
            WndClass.cbWndExtra    = 0;
            WndClass.hInstance     = InstanceHandle;
            WndClass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
            WndClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
            WndClass.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
            WndClass.lpszMenuName  = NULL;
            WndClass.lpszClassName = EchoClassStr;
            if (!RegisterClass(&WndClass)) 
                return(FALSE);
             }
             return(TRUE);
    }
      

  2.   

    WS2_32.LIB就够了,通常不需要WSOCK32.LIB
    错误信息是没有main函数。有可能你创建的工程和代码原来的工程类型不同!比如说原来的工程Win32 Application,但你新建一个Console的工程,直接拷过来的代码有时候是不能直接用的,要做些改变。
      

  3.   

    WS2_32.LIB和WSOCK32.LIB有什么不同?
      

  4.   

    是不是一个是winsock1,另一个是winsock2?
      

  5.   

    没错
    ws2_32.lib是winsock2,wsock32.lib可以看作是winsock1