天天看點

使用C/C++實作Socket聊天程式

使用C/C++實作Socket聊天程式

Initsock.h檔案

  1. // initsock.h檔案
  2. #include <winsock2.h>
  3. #include <stdlib.h>
  4. #include <conio.h>
  5. #include <stdio.h>
  6. #pragma comment(lib,"WS2_32") // 連結到WS2_32.lib
  7. class CInitSock
  8. {
  9. public:
  10.    CInitSock(BYTE minorVer = 2, BYTE majorVer = 2)
  11.     {
  12.        // 初始化WS2_32.dll
  13.        WSADATA wsaData;
  14.        WORD sockVersion = MAKEWORD(minorVer, majorVer);
  15.        if(::WSAStartup(sockVersion, &wsaData) != 0)
  16.        {
  17.            exit(0);
  18.        }
  19.     }
  20.    ~CInitSock()
  21.    {
  22.        ::WSACleanup();
  23.     }
  24. };

TCP版

TCPClient.cpp檔案

  1. //////////////////////////////////////////////////////////
  2. // TCPClient.cpp檔案
  3. /*
  4.                 《使用說明》
  5. 0.運作程式前請檢視是否将initsock.h
  6.   檔案引入到項目中。
  7. 1.首先修改聊天對方的IP位址
  8. 2.請首先運作服務端(TCPServer)程式,再運作用戶端(TCPClient)程式:
  9.   如配置正确服務端會收到相關連接配接資訊。
  10. 3.連接配接成功後,需要由伺服器端首先發起會話(輸入消息并确認發送),
  11.   用戶端收到消息後才能輸入消息并确認發送到伺服器端。
  12.   并且雙方每次隻能發送一條消息。如想發送第二條消息,需要等待該方成功
  13.   接受到另一方的消息後才能繼續輸入消息。
  14. */
  15. #include "InitSock.h"
  16. #include <stdio.h>
  17. #include <iostream.h>
  18. CInitSock initSock; // 初始化Winsock庫
  19. int main()
  20. {
  21.    // 建立套節字
  22.    SOCKET s = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  23.    if(s == INVALID_SOCKET)
  24.     {
  25.        printf(" Failed socket() \n");
  26.        return 0;
  27.     }
  28.    // 也可以在這裡調用bind函數綁定一個本地位址
  29.    // 否則系統将會自動安排
  30.    // 填寫遠端位址資訊
  31.    sockaddr_in servAddr;
  32.    servAddr.sin_family = AF_INET;
  33.    servAddr.sin_port = htons(4567);
  34.    // 注意,這裡要填寫伺服器程式(TCPServer程式)所在機器的IP位址
  35.    // 如果你的計算機沒有聯網,直接使用127.0.0.1即可
  36.    servAddr.sin_addr.S_un.S_addr = inet_addr("192.168.1.129");
  37.    if(::connect(s, (sockaddr*)&servAddr, sizeof(servAddr)) == -1)
  38.     {
  39.        printf(" Failed connect() \n");
  40.        return 0;
  41.     }
  42.    char buff[256];
  43.    char szText[256] ;
  44.    while(TRUE)
  45.     {
  46.        //從伺服器端接收資料
  47.        int nRecv = ::recv(s, buff, 256, 0);
  48.        if(nRecv > 0)
  49.        {
  50.            buff[nRecv] = '\0';
  51.            printf("接收到資料:%s\n", buff);
  52.        }
  53.        // 向伺服器端發送資料
  54.        cin>>szText ;
  55.        szText[255] = '\0';
  56.         ::send(s, szText, strlen(szText), 0) ;
  57.     }
  58.    // 關閉套節字
  59.    ::closesocket(s);
  60.    return 0;
  61. }

TCPServer.cpp檔案

  1. // TCPServer.cpp檔案
  2. /*
  3.                 《使用說明》
  4. 0.運作程式前請檢視是否将initsock.h
  5.   檔案引入到項目中。
  6. 1.首先修改聊天對方的IP位址
  7. 2.請首先運作服務端(TCPServer)程式,再運作用戶端(TCPClient)程式:
  8.   如配置正确服務端會收到相關連接配接資訊。
  9. 3.連接配接成功後,需要由伺服器端首先發起會話(輸入消息并确認發送),
  10.   用戶端收到消息後才能輸入消息并确認發送到伺服器端。
  11.   并且雙方每次隻能發送一條消息。如想發送第二條消息,需要等待該方成功
  12.   接受到另一方的消息後才能繼續輸入消息。
  13. */
  14. #include "InitSock.h"
  15. #include <stdio.h>
  16. #include <iostream.h>
  17. CInitSock initSock; // 初始化Winsock庫
  18. int main()
  19. {
  20.    // 建立套節字
  21.    SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  22.    if(sListen == INVALID_SOCKET)
  23.     {
  24.        printf("Failed socket() \n");
  25.        return 0;
  26.     }
  27.    // 填充sockaddr_in結構
  28.    sockaddr_in sin;
  29.    sin.sin_family = AF_INET;
  30.    sin.sin_port = htons(4567);
  31.    sin.sin_addr.S_un.S_addr = INADDR_ANY;
  32.    // 綁定這個套節字到一個本地位址
  33.    if(::bind(sListen, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)
  34.     {
  35.         printf("Failed bind() \n");
  36.        return 0;
  37.     }
  38.    // 進入監聽模式
  39.    if(::listen(sListen, 2) == SOCKET_ERROR)
  40.     {
  41.        printf("Failed listen() \n");
  42.        return 0;
  43.     }
  44.    // 循環接受客戶的連接配接請求
  45.    sockaddr_in remoteAddr;
  46.    int nAddrLen = sizeof(remoteAddr);
  47.    SOCKET sClient = 0;
  48.    char szText[] = " TCP Server Demo! \r\n";
  49.    while(sClient==0)
  50.     {
  51.        // 接受一個新連接配接
  52.        sClient = ::accept(sListen, (SOCKADDR*)&remoteAddr, &nAddrLen);
  53.        if(sClient == INVALID_SOCKET)
  54.        {
  55.            printf("Failed accept()");
  56.        }
  57.        printf("接受到一個連接配接:%s \r\n", inet_ntoa(remoteAddr.sin_addr));
  58.        continue ;
  59.     }
  60.    while(TRUE)
  61.     {
  62.        // 向用戶端發送資料
  63.        gets(szText) ;
  64.        ::send(sClient, szText, strlen(szText), 0);
  65.        // 從用戶端接收資料
  66.        char buff[256] ;
  67.        int nRecv = ::recv(sClient, buff, 256, 0);
  68.        if(nRecv > 0)
  69.        {
  70.            buff[nRecv] = '\0';
  71.            printf(" 接收到資料:%s\n", buff);
  72.        }
  73.     }
  74.    // 關閉同用戶端的連接配接
  75.    ::closesocket(sClient);
  76.    // 關閉監聽套節字
  77.    ::closesocket(sListen);
  78.    return 0;
  79. }

UDP版

  1. // Chat.cpp : Defines the entry point forthe console application.
  2. //
  3. /*
  4.                 《使用說明》
  5. 0.運作程式前請檢視是否将initsock.h
  6.   檔案引入到項目中。
  7. 1.首先修改聊天對方的IP位址
  8. 2.運作程式:如配置正确另一方會收到相關連接配接資訊。
  9. 3.輸入消息:在每次輸入完欲發送的消息後,需要連續敲擊兩次回車。
  10. 4.本程式有諸多缺陷:對使用者輸入的消息不能即時回顯到控制台,
  11.   需要在敲擊兩次回車後回顯到螢幕。
  12. */
  13. #include "stdafx.h"
  14. #include <iostream>
  15. #include <stdlib.h>
  16. #include <STDIO.H>
  17. #include <windows.h>
  18. #include "InitSock.h"
  19. using namespace std;
  20. CInitSock initSock; // 初始化Winsock庫
  21. DWORD receiverMark ; //接收消息者線程辨別符
  22. DWORD senderMark ;//發送者線程辨別符
  23. /**
  24. *定義信号量
  25. */
  26. DWORD WINAPI Receiver(LPVOID) ;
  27. DWORD WINAPI Sender(LPVOID) ;
  28. // 接收資料
  29. char buff[1024];
  30. sockaddr_in addr;
  31. int nLen = sizeof(addr);
  32. SOCKET s ;
  33. int main(int argc, char *argv[])
  34. {
  35.    // 建立套節字
  36.     s= ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  37.    //u_long iMode = 1;
  38.    //ioctlsocket(s, FIONBIO, &iMode);
  39.    if(s == INVALID_SOCKET)
  40.     {
  41.        printf("Failed socket() \n");
  42.        return 0;
  43.     }
  44.    // 填充sockaddr_in結構
  45.    sockaddr_in sin;
  46.    sin.sin_family = AF_INET;
  47.    sin.sin_port = htons(4567);
  48.    sin.sin_addr.S_un.S_addr = INADDR_ANY;
  49.    addr.sin_family = AF_INET;
  50.    addr.sin_port = htons(4567);
  51.    // 注意,這裡要填寫伺服器程式所在機器的IP位址
  52.    // 如果你的計算機沒有聯網,直接使用127.0.0.1即可
  53.    addr.sin_addr.S_un.S_addr = inet_addr("192.168.1.129");
  54.    // 綁定這個套節字到一個本地位址
  55.    if(::bind(s, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)
  56.     {
  57.        printf("Failed bind() \n");
  58.        return 0;
  59.     }
  60.    // 發送資料
  61.    char szText[] = "PC請求連接配接... \r\n";
  62.    ::sendto(s, szText, strlen(szText), 0, (sockaddr*)&addr,sizeof(addr));
  63.    CreateThread(NULL,0,Receiver,NULL,0,&receiverMark);
  64.    CreateThread(NULL,0,Sender,NULL,0,&senderMark);
  65.    bool isContinue = true ;
  66.    while(isContinue)
  67.    {
  68.          if(getche()==96){ //按~後終止程式運作
  69.                isContinue = false;
  70.           }
  71.     }
  72.    system("PAUSE");
  73.    return 0;
  74. }
  75. /**
  76. *接收者
  77. */
  78. DWORD WINAPI Receiver(LPVOID lpParam )
  79. {
  80.    while(1)
  81.     {
  82.        int nRecv = ::recvfrom(s, buff, 1024, 0, (sockaddr*)&addr,&nLen);
  83.        if(nRecv > 0)
  84.        {
  85.            buff[nRecv] = '\0';
  86.            printf(" Received data(%s):%s\n", ::inet_ntoa(addr.sin_addr), buff);
  87.        }
  88.     }
  89.    return 0;
  90. }
  91. /**
  92. *發送者
  93. */
  94. DWORD WINAPI Sender(LPVOID lpPara)
  95. {
  96.    while(1)
  97.     {
  98.        cout<<"Input your message: " ;
  99.        // 發送資料
  100.        char text[256] ;
  101.        cin>>text ;
  102.        text[255] = '\0' ;
  103.        cout<<text<<endl ;
  104.        ::sendto(s, text, strlen(text), 0, (sockaddr*)&addr, sizeof(addr));
  105.     }
  106.    return 0;
  107. }

本文來自CSDN部落格,轉載請标明出處:http://blog.csdn.net/yexianyi/archive/2008/12/10/3486766.aspx

使用C/C++實作Socket聊天程式

 解決該問題的思路

 解決該問題的整體方案不外有二:

(1)基于TCP的Socket連接配接;(2)基于UDP的Socket連接配接;

但是,針對每種方案又各有很多具體的實作方法。

在本次實驗中,我先後開發了基于TCP連接配接和UDP連接配接的Socket聊天程式。具體實作思路如下:

(一)  基于TCP連接配接Socket聊天程式

基于該連接配接的聊天程式需要至少具備一個伺服器端(Server)和一個用戶端(Client)。在本程式中,一個使用者作為Server端,另一個使用者作為Client端。也就是說,作為Server端的使用者,需要首先啟動程式,等待Client端的連接配接請求。當TCP連接配接握手以後,雙方方可進行互動。(注:在本程式中Server端并不是單獨存在。它也可以向他的Client端發送消息。)但是本程式實作的互動功能十分簡單,具有很多限制。當Client端與Server端握手以後,Server端需要首先發起會話;Client端在收到消息後再回複一條消息給Server端;同樣,Server端在收到消息後再回複一條消息給Client端……以此類推。并且,無論是Server端還是Client端每次發送消息隻能發送一條。

造成互動操作具有諸多限制的主要原因是,我在Server端和Client端使用了一個While循環,它們的僞代碼分别如下:

Client端

 Server端

   while(TRUE)

    {

       從Server端接收消息

       {

          …

}

       向Server端發送消息

       {

          …

}

}

 while(TRUE)

    {

       向Client端發送消息

       {

           …

}

       從Client端接收消息

       {

          …

}

    }

(二)  基于UDP連接配接Socket聊天程式

基于該連接配接的聊天程式不需要具備伺服器端(Server),每個用戶端(Client)既是伺服器端也是用戶端。也就是說每個Client端自身既可以自行接收其它使用者發來的消息,也可以向其它Client端發送消息,不需要事先與其他使用者進行握手連接配接。

由于在預設情況下WinSock接口的recvfrom()和sendto()都會在被調用時阻塞目前線程,也就是說如果程式正在接受其他使用者發來的資料,那麼它就不能夠執行發送資料的任務,反之相同。是以為解決該問題一般有以下幾種解決方案:采用Select模型、WSAAsyncSelect模型、WSAEventSelect模型、重疊(Overlapped)模型和完成接口(Completion port)模型。在本程式中,由于我沒能在短時間内學會上述方案中的任一種,是以采用了多線程技術去實作消息接收和發送的同步問題。也就是說,在程式中建立兩個線程,一個線程負責發送消息,另一個消息負責接受消息。兩個線程交替運作,進而達到同時收發消息的目的。當然采用多線程方式解決消息收發同步問題可以移除上個程式中每個使用者一次隻能發送一條消息的限制。

本周開發源代碼

 代碼的功能簡述

 使用C/C++實作Socket聊天程式:

TCP版:伺服器端使用者和用戶端使用者在成功連接配接後,其中一方通過控制台輸入消息,依次輪流向另一方發送資料。要求,伺服器端首先發起會話,并且雙方每次隻能發送一條消息。

UDP版:任一端使用者通過指定IP位址将消息發送到另一端的使用者。互動雙方通過控制台輸入消息向另一方發送資料。沒有任何發送限制。

開發的收獲

 了解了TCP連接配接和UDP連接配接的基本原理和工作過程。

複習了關于Windows多線程及程序同步的相關知識。

開發中碰到的主要困難

 對于TCP版:

    在考慮如何解決消息的收發同步問題上遇到了困難。最終使用了不佳方案:通過在伺服器端和用戶端分别運作while循環并依次進行資料收發工作的方式解決資料收發同步問題。

對于UDP版:

    同樣在考慮如何解決消息的收發同步問題上遇到了困難。但這次使用了多線程解決該問題。

 開發中未能解決的問題

 對于UDP版:

為何第一次消息輸入完畢敲擊一次回車後,隻有消息的第一個字元沒能發送出去,而其它字元卻可以被成功發送出去?而且當第二次輸入消息敲回車後消息就能被全部發送出去?

為何消息輸入完畢後需要按兩次Enter鍵才能将消息發送到另一端?

為什麼輸入的消息不能即時回顯到發送者螢幕上?隻有當敲擊二次回車後使用者輸入的欲發送消息才會顯現出來?

如何才能避免使用者在輸入消息的同時也能正常接收消息?也就是不至于打斷使用者已輸入的消息的前提下,顯示接收到的消息。

針對本周訓練内容自己設計的案例

 案例的主要功能

 同代碼的功能簡述

用到的基本知識

 相關Winsock程式設計接口;TCP連接配接和UDP連接配接基本工作原理;Windows多線程;

程序同步

程式注意了哪些規範

 代碼格式、常量的定義、函數的聲明

你進行了哪些測試

 略

程式進行了哪些有效性檢查

 略

你是如何保證程式的高效率的

 略

本文來自CSDN部落格,轉載請标明出處:http://blog.csdn.net/yexianyi/archive/2008/12/10/3486766.aspx

北航軟體學院《一級實踐》實驗報告

學号:GS0821594    姓名:葉現一                  第 13 周

内容

訓練

 使用C/C++實作Socket聊天程式

 解決該問題的思路

 解決該問題的整體方案不外有二:

(1)基于TCP的Socket連接配接;(2)基于UDP的Socket連接配接;

但是,針對每種方案又各有很多具體的實作方法。

在本次實驗中,我先後開發了基于TCP連接配接和UDP連接配接的Socket聊天程式。具體實作思路如下:

(一)  基于TCP連接配接Socket聊天程式

基于該連接配接的聊天程式需要至少具備一個伺服器端(Server)和一個用戶端(Client)。在本程式中,一個使用者作為Server端,另一個使用者作為Client端。也就是說,作為Server端的使用者,需要首先啟動程式,等待Client端的連接配接請求。當TCP連接配接握手以後,雙方方可進行互動。(注:在本程式中Server端并不是單獨存在。它也可以向他的Client端發送消息。)但是本程式實作的互動功能十分簡單,具有很多限制。當Client端與Server端握手以後,Server端需要首先發起會話;Client端在收到消息後再回複一條消息給Server端;同樣,Server端在收到消息後再回複一條消息給Client端……以此類推。并且,無論是Server端還是Client端每次發送消息隻能發送一條。

造成互動操作具有諸多限制的主要原因是,我在Server端和Client端使用了一個While循環,它們的僞代碼分别如下:

Client端

 Server端

   while(TRUE)

    {

       從Server端接收消息

       {

          …

}

       向Server端發送消息

       {

          …

}

}

 while(TRUE)

    {

       向Client端發送消息

       {

          …

}

       從Client端接收消息

       {

          …

}

    }

(二)  基于UDP連接配接Socket聊天程式

基于該連接配接的聊天程式不需要具備伺服器端(Server),每個用戶端(Client)既是伺服器端也是用戶端。也就是說每個Client端自身既可以自行接收其它使用者發來的消息,也可以向其它Client端發送消息,不需要事先與其他使用者進行握手連接配接。

由于在預設情況下WinSock接口的recvfrom()和sendto()都會在被調用時阻塞目前線程,也就是說如果程式正在接受其他使用者發來的資料,那麼它就不能夠執行發送資料的任務,反之相同。是以為解決該問題一般有以下幾種解決方案:采用Select模型、WSAAsyncSelect模型、WSAEventSelect模型、重疊(Overlapped)模型和完成接口(Completion port)模型。在本程式中,由于我沒能在短時間内學會上述方案中的任一種,是以采用了多線程技術去實作消息接收和發送的同步問題。也就是說,在程式中建立兩個線程,一個線程負責發送消息,另一個消息負責接受消息。兩個線程交替運作,進而達到同時收發消息的目的。當然采用多線程方式解決消息收發同步問題可以移除上個程式中每個使用者一次隻能發送一條消息的限制。

本周開發源代碼

 代碼的功能簡述

 使用C/C++實作Socket聊天程式:

TCP版:伺服器端使用者和用戶端使用者在成功連接配接後,其中一方通過控制台輸入消息,依次輪流向另一方發送資料。要求,伺服器端首先發起會話,并且雙方每次隻能發送一條消息。

UDP版:任一端使用者通過指定IP位址将消息發送到另一端的使用者。互動雙方通過控制台輸入消息向另一方發送資料。沒有任何發送限制。

開發的收獲

 了解了TCP連接配接和UDP連接配接的基本原理和工作過程。

複習了關于Windows多線程及程序同步的相關知識。

開發中碰到的主要困難

 對于TCP版:

    在考慮如何解決消息的收發同步問題上遇到了困難。最終使用了不佳方案:通過在伺服器端和用戶端分别運作while循環并依次進行資料收發工作的方式解決資料收發同步問題。

對于UDP版:

    同樣在考慮如何解決消息的收發同步問題上遇到了困難。但這次使用了多線程解決該問題。

 開發中未能解決的問題

 對于UDP版:

為何第一次消息輸入完畢敲擊一次回車後,隻有消息的第一個字元沒能發送出去,而其它字元卻可以被成功發送出去?而且當第二次輸入消息敲回車後消息就能被全部發送出去?

為何消息輸入完畢後需要按兩次Enter鍵才能将消息發送到另一端?

為什麼輸入的消息不能即時回顯到發送者螢幕上?隻有當敲擊二次回車後使用者輸入的欲發送消息才會顯現出來?

如何才能避免使用者在輸入消息的同時也能正常接收消息?也就是不至于打斷使用者已輸入的消息的前提下,顯示接收到的消息。

針對本周訓練内容自己設計的案例

 案例的主要功能

 同代碼的功能簡述

用到的基本知識

 相關Winsock程式設計接口;TCP連接配接和UDP連接配接基本工作原理;Windows多線程;

程序同步

程式注意了哪些規範

 代碼格式、常量的定義、函數的聲明

你進行了哪些測試

 略

程式進行了哪些有效性檢查

 略

你是如何保證程式的高效率的

 略

注意:實驗報告和案例源代碼須在本次小組讨論會前送出                                                                                                                   

本文來自CSDN部落格,轉載請标明出處:http://blog.csdn.net/yexianyi/archive/2008/12/10/3486766.aspx

view plaincopy to clipboardprint?

  1. #pragmacomment(lib,"ws2_32.lib")
  2. #include<winsock2.h>
  3. #include<iostream>
  4. #include<string>
  5. usingnamespace std;
  6. string strCurMsg="";
  7. void recvProc(SOCKET sockConnect)
  8. {
  9.     char msgRcv[100]={0};
  10.     while(true)
  11.     {
  12.         if(SOCKET_ERROR == recv(sockConnect,msgRcv,sizeof(msgRcv),0))
  13.         {
  14.         cout<<"\nHe is leaving";
  15.         return;
  16.         }
  17.         if(msgRcv[0]!='')
  18.         {
  19.         strCurMsg.erase(strCurMsg.end()-7,strCurMsg.end());
  20.         strCurMsg+="He said: ";
  21.         strCurMsg+=msgRcv;
  22.         strCurMsg+=’n’;
  23.         strCurMsg+="input:";
  24.         system("cls");
  25.         cout<<strCurMsg;
  26.         }
  27.     }
  28. }
  29. int main(int argc, char* argv[])
  30. {
  31.     WORD wVersionRequested;
  32.     WSADATA wsaData;
  33.     int err;
  34.     wVersionRequested = MAKEWORD( 1, 1 );
  35.     err = WSAStartup( wVersionRequested, &wsaData );
  36.     if ( 0 )
  37.     {
  38.         return 1;
  39.     }
  40.     if (LOBYTE( wsaData.wVersion ) != 1 || HIBYTE(wsaData.wVersion ) != 1)
  41.     {
  42.         WSACleanup();
  43.         return 1;
  44.     }
  45.     SOCKET sockSrv = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  46.     sockaddr_in addrSrv;
  47.     memset(&addrSrv,0,sizeof(addrSrv));
  48.     addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
  49.     addrSrv.sin_family=AF_INET;
  50.     addrSrv.sin_port=htons(5000);
  51.     if(bind(sockSrv,(sockaddr*)&addrSrv,sizeof(sockaddr)) == SOCKET_ERROR)
  52.     {
  53.         cout<<"bind error"<<endl;
  54.     }
  55.     if(listen(sockSrv,5) == SOCKET_ERROR)
  56.     {
  57.         cout<<"listen error"<<endl;
  58.     }
  59.     SOCKADDR_IN addrClient;
  60.     int len = sizeof(sockaddr);
  61.     while(true)
  62.     {
  63.         cout<<"Waiting.....";
  64.         SOCKET sockConnect = accept(sockSrv,(sockaddr*)&addrClient,&len);
  65.         if(sockConnect == INVALID_SOCKET)
  66.         {
  67.             cout<<"invalid socket"<<endl;
  68.             return 0;
  69.         }
  70.         else
  71.         {
  72.             cout<<"He is coming\n";
  73.         }
  74.         CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)recvProc,(void*)sockConnect,0,NULL);
  75.         while(true)
  76.         {
  77.             char buf[100]={0};
  78.             strCurMsg+="input:";
  79.             system("cls");
  80.             cout<<strCurMsg;
  81.             cin.getline(buf,100);
  82.             strCurMsg.erase(strCurMsg.end()-7,strCurMsg.end());
  83.             strCurMsg+="You said:";
  84.             strCurMsg+=buf;
  85.             strCurMsg+='n';
  86.             send(sockConnect,buf,sizeof(buf),0);
  87.         }
  88.         closesocket(sockConnect);
  89.     }
  90.     WSACleanup();
  91.     return 0;
  92. }
  93. #pragmacomment(lib,"ws2_32.lib")
  94. #include<winsock2.h>
  95. #include<iostream>
  96. #include<string>
  97. usingnamespace std;
  98. string strCurMsg="";
  99. void recvProc(SOCKET sockConnect)
  100. {
  101.     char msgRcv[100]={0};
  102.     while(true)
  103.     {
  104.         if(SOCKET_ERROR == recv(sockConnect,msgRcv,sizeof(msgRcv),0))
  105.         {
  106.             cout<<"\nHe is leaving";
  107.             return;
  108.         }
  109.         if(msgRcv[0]!=’’)
  110.         {
  111.             strCurMsg.erase(strCurMsg.end()-7,strCurMsg.end());
  112.             strCurMsg+="He said: ";
  113.             strCurMsg+=msgRcv;
  114.             strCurMsg+='n';
  115.             strCurMsg+="input:";
  116.             system("cls");
  117.             cout<<strCurMsg;
  118.         }
  119.     }
  120. }
  121. int main(int argc, char* argv[])
  122. {
  123.     WORD wVersionRequested;
  124.     WSADATA wsaData;
  125.     int err;
  126.     wVersionRequested = MAKEWORD( 1, 1 );
  127.     err = WSAStartup( wVersionRequested, &wsaData );
  128.     if ( 0 )
  129.     {
  130.         return 1;
  131.     }
  132.     if (LOBYTE( wsaData.wVersion ) != 1||HIBYTE(wsaData.wVersion ) != 1)
  133.     {
  134.         WSACleanup();
  135.         return 1;
  136.     }
  137.     SOCKET sockSrv = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  138.     sockaddr_in addrSrv;
  139.     memset(&addrSrv,0,sizeof(addrSrv));
  140.     addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
  141.     addrSrv.sin_family = AF_INET;
  142.     addrSrv.sin_port = htons(5000);
  143.     if(bind(sockSrv,(sockaddr*)&addrSrv,sizeof(sockaddr)) == SOCKET_ERROR)
  144.     {
  145.         cout<<"bind error"<<endl;
  146.     }
  147.     if(listen(sockSrv,5) == SOCKET_ERROR)
  148.     {
  149.         cout<<"listen error"<<endl;
  150.     }
  151.     SOCKADDR_IN addrClient;
  152.     int len = sizeof(sockaddr);
  153.     while(true)
  154.     {
  155.         cout<<"Waiting.....";
  156.         SOCKET sockConnect = accept(sockSrv,(sockaddr*)&addrClient,&len);
  157.         if(sockConnect == INVALID_SOCKET)
  158.         {
  159.             cout<<"invalid socket"<<endl;
  160.             return 0;
  161.         }
  162.         else
  163.         {
  164.             cout<<"He is coming\n";
  165.         }
  166.         CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)recvProc,(void*)sockConnect,0,NULL);
  167.         while(true)
  168.         {
  169.             char buf[100]={0};
  170.             strCurMsg+="input:";
  171.             system("cls");
  172.             cout<<strCurMsg;
  173.             cin.getline(buf,100);
  174.             strCurMsg.erase(strCurMsg.end()-7,strCurMsg.end());
  175.             strCurMsg+="You said:";
  176.             strCurMsg+=buf;
  177.             strCurMsg+='n';
  178.             send(sockConnect,buf,sizeof(buf),0);
  179.         }
  180.         closesocket(sockConnect);
  181.     }
  182.     WSACleanup();
  183.     return 0;
  184. }

全國計算機等級考試網,加入收藏用戶端程式代碼:

viewplaincopy to clipboardprint?

  1. #pragmacomment(lib,"ws2_32.lib")
  2. #include<winsock2.h>
  3. #include<iostream>
  4. #include<string>
  5. usingnamespace std;
  6. string strCurMsg="";
  7. void recvProc(SOCKET sockClient)
  8. {
  9.     char msgRcv[100]={0};
  10.     while(true)
  11.     {
  12.         if(SOCKET_ERROR==recv(sockClient,msgRcv,sizeof(msgRcv),0))
  13.         {
  14.             cout<<"\nHe is leaving";
  15.             return;
  16.         }
  17.         if(msgRcv[0]!=’’)
  18.         {
  19.             strCurMsg.erase(strCurMsg.end()-7,strCurMsg.end());
  20.             strCurMsg+="He said: ";
  21.             strCurMsg+=msgRcv;
  22.             strCurMsg+=’n’;
  23.             strCurMsg+="input:";
  24.             system("cls");
  25.             cout<<strCurMsg;
  26.         }
  27.     }
  28. }
  29. int main(int argc, char* argv[])
  30. {
  31.     WORD wVersionRequested;
  32.     WSADATA wsaData;
  33.     int err;
  34.     wVersionRequested = MAKEWORD( 1, 1 );
  35.     err = WSAStartup( wVersionRequested, &wsaData );
  36.     if ( 0 ) {
  37.         return 1;
  38.     }
  39.     if (LOBYTE( wsaData.wVersion ) != 1 || HIBYTE(wsaData.wVersion ) != 1)
  40.     {
  41.         WSACleanup();
  42.         return 1;
  43.     }
  44.     SOCKET sockClient = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  45.     SOCKADDR_IN addrSrv;
  46.     addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
  47.     addrSrv.sin_family=AF_INET;
  48.     addrSrv.sin_port=htons(5000);
  49.     if(connect(sockClient,(sockaddr*)&addrSrv,sizeof(sockaddr)) == SOCKET_ERROR)
  50.     {
  51.         cout<<"connected failed\n";
  52.         return 1;
  53.     }
  54.     else
  55.     {
  56.         cout<<"connect OK\n";
  57.     }
  58.     CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)recvProc,(void*)sockClient,    0,NULL);
  59.     while(true)
  60.     {
  61.         char buf[100]={0};
  62.         strCurMsg+="input:";
  63.         system("cls");
  64.         cout<<strCurMsg;
  65.         cin.getline(buf,100);
  66.         strCurMsg.erase(strCurMsg.end()-7,strCurMsg.end());
  67.         strCurMsg+="You said:";
  68.         strCurMsg+=buf;
  69.         strCurMsg+='n';
  70.         send(sockClient,buf,sizeof(buf),0);
  71.     }
  72.     closesocket(sockClient);
  73.     WSACleanup();
  74.     return 0;
  75. }
  76. #pragma comment(lib,"ws2_32.lib")
  77. #include<winsock2.h>
  78. #include<iostream>
  79. #include<string>
  80. usingnamespace std;
  81. string strCurMsg="";
  82. void recvProc(SOCKET sockClient)
  83. {
  84.     char msgRcv[100]={0};
  85.     while(true)
  86.     {
  87.         if(SOCKET_ERROR == recv(sockClient,msgRcv,sizeof(msgRcv),0))
  88.         {
  89.             cout<<"\nHe is leaving";
  90.             return;
  91.         }
  92.         if(msgRcv[0]!=’’)
  93.         {
  94.             strCurMsg.erase(strCurMsg.end()-7,strCurMsg.end());
  95.             strCurMsg+="He said: ";
  96.             strCurMsg+=msgRcv;
  97.             strCurMsg+='n';
  98.             strCurMsg+="input:";
  99.             system("cls");
  100.             cout<<strCurMsg;
  101.         }
  102.     }
  103. }
  104. int main(int argc, char* argv[])
  105. {
  106.     WORD wVersionRequested;
  107.     WSADATA wsaData;
  108.     int err;
  109.     wVersionRequested = MAKEWORD( 1, 1 );
  110.     err = WSAStartup( wVersionRequested, &wsaData );
  111.     if ( 0 )
  112.     {
  113.         return 1;
  114.     }
  115.     if (LOBYTE( wsaData.wVersion ) != 1 || HIBYTE(wsaData.wVersion ) != 1)
  116.     {
  117.         WSACleanup();
  118.         return 1;
  119.     }
  120.     SOCKET sockClient=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  121.     SOCKADDR_IN addrSrv;
  122.     addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
  123.     addrSrv.sin_family=AF_INET;
  124.     addrSrv.sin_port=htons(5000);
  125.     if(connect(sockClient,(sockaddr*)&addrSrv,sizeof(sockaddr)) == SOCKET_ERROR)
  126.     {
  127.          cout<<"connected failed\n";
  128.         return 1;
  129.     }
  130.     else
  131.     {
  132.         cout<<"connect OK\n";
  133.     }
  134.     CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)recvProc,(void*)sockClient,0,NULL);
  135.     while(true)
  136.     {
  137.         char buf[100]={0};
  138.         strCurMsg+="input:";
  139.         system("cls");
  140.         cout<<strCurMsg;
  141.         cin.getline(buf,100);
  142.         strCurMsg.erase(strCurMsg.end()-7,strCurMsg.end());
  143.         strCurMsg+="You said:";
  144.         strCurMsg+=buf;
  145.         strCurMsg+='n';
  146.         send(sockClient,buf,sizeof(buf),0);
  147.     }
  148.     closesocket(sockClient);
  149.     WSACleanup();
  150.     return 0;
  151. }

繼續閱讀