C語言創建Socket實現雙工通信


實現簡單的Socket通信案例(個人嘗試)

服務端代碼(Server)

#include <stdio.h>  
#include <winsock2.h>  
#pragma comment(lib,"ws2_32.lib")
#define PORT 9999 

int main()
{
    WSADATA WSAData;
    SOCKET sock, msgsock;
    struct sockaddr_in ServerAddr;

    if (WSAStartup(MAKEWORD(2, 0), &WSAData) != SOCKET_ERROR)
    {
        ServerAddr.sin_family = AF_INET;
        ServerAddr.sin_port = htons(PORT);
        ServerAddr.sin_addr.s_addr = INADDR_ANY;

        sock = socket(AF_INET, SOCK_STREAM, 0);
        int BindRet = bind(sock, (LPSOCKADDR)&ServerAddr, sizeof(ServerAddr));
        int LinsRet = listen(sock, 10);
        printf("------------------------------------------------------------------------------------------\n");
        printf("綁定狀態: %d\t 偵聽狀態: %d\t 綁定端口: %d\n", BindRet, LinsRet, ntohs(ServerAddr.sin_port));
        printf("------------------------------------------------------------------------------------------\n");
    }

    while (1)
    {
        char buf[1024];
        msgsock = accept(sock, (LPSOCKADDR)0, (int *)0);
        memset(buf, 0, sizeof(buf));
        recv(msgsock, buf, 1024, 0);
        printf("客戶IP: %s\t 端口:%d\t 數據:%s\n", inet_ntoa(ServerAddr.sin_addr), htons(ServerAddr.sin_port),buf);
        if (!strcmp(buf, "Success"))
        {
            printf("客戶端已就緒...\n");
        }
        closesocket(msgsock);
    }
    closesocket(sock);
    WSACleanup();
    return 0;
}
View Code

客戶端代碼(Client)

#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib,"ws2_32.lib")
#define IP "127.0.0.1"
#define PORT 9999

//#ifdef _MSC_VER
//#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )
//#endif

int main()
{
    while (1)
    {
        WSADATA WSAData;
        SOCKET sock;
        struct sockaddr_in ClientAddr;

        if (WSAStartup(MAKEWORD(2, 0), &WSAData) != SOCKET_ERROR)
        {
            ClientAddr.sin_family = AF_INET;                //指Internet域
            ClientAddr.sin_port = htons(PORT);            //指定服務端所預留的端口
            ClientAddr.sin_addr.s_addr = inet_addr(IP);    //指定服務端所綁定的IP地址

            sock = socket(AF_INET, SOCK_STREAM, 0);
            int Ret = connect(sock, (LPSOCKADDR)&ClientAddr, sizeof(ClientAddr));
            if (Ret == 0)
            {
                char Status[] = "Success";
                int ServerRet = send(sock, Status, sizeof(Status), 0);
                if (ServerRet != 0)
                {
                    printf("發送給服務器Success狀態成功..\n");
                }
            }
        }
        closesocket(sock);
        WSACleanup();
        Sleep(5000);
    }
    return 0;
}
View Code

 

實現Socket單工通信案例

服務端代碼(Server)

#include <stdio.h>  
#include <winsock2.h>  
#pragma comment(lib,"ws2_32.lib")    //把ws2_32.lib加到Link頁的連接庫  
#define PORT 15001                    //通信的端口(指服務器端)
#define ERROR 0  
#define BUFFER_SIZE 1024            //注意:此Server端數據接收緩沖區 >= Client端數據發送緩沖區 ,否則造成緩沖區溢出
/*
    服務端原理:
        1、服務器進程創建套接字
        2、將本地地址綁定到所創建的套接字上,以三元組{<通信協議>,<IP地址>,<端口號>}在網絡上標識該套接字
        3、將套接字置入監聽模式,並准備接受連接請求
*/
int main()  
{  
    WSADATA WSAData;  
    if(WSAStartup(MAKEWORD(2,0),&WSAData)==SOCKET_ERROR)  //啟動winsock ,WSAStartup()函數對Winsock DLL進行初始化
    {  
        printf("Socket initialize fail!\n");  
        exit(1);  
    }  
    SOCKET sock;                                        //服務進程創建套接字句柄(用於監聽)
    if((sock=socket(AF_INET,SOCK_STREAM,0))==ERROR)        //調用socket()函數創建一個流套接字,參數(網絡地址類型,套接字類型,網絡協議)
    { 
        printf("Socket create!\n");  
        WSACleanup();  
        exit(1);  
    }  
    struct sockaddr_in ServerAddr;            //sockaddr_in結構用來標識TCP/IP協議下的地址,可強制轉換為sockaddr結構
    ServerAddr.sin_family=AF_INET;            //sin_family字段必須設為AF_INET,表示該Socket處於Internet域
    ServerAddr.sin_port=htons(PORT);        //sin_port字段用於指定服務端口,注意避免沖突
    ServerAddr.sin_addr.s_addr=INADDR_ANY;  //sin_addr字段用於把一個IP地址保存為一個4字節的數,無符號長整型,根據不同用法還可表示本地或遠程IP地址
    if(bind(sock,(LPSOCKADDR)&ServerAddr,sizeof(ServerAddr))==SOCKET_ERROR)  //調用bind()函數將本地地址綁定到所創建的套接字上,以在網絡上標識該套接字
    {   
        printf("Bind fail!\n");  
        closesocket(sock);  
        WSACleanup();  
        exit(1);  
    }  
    printf("Server Socket Port:%d\n",ntohs(ServerAddr.sin_port));  
    if(listen(sock,10)==SOCKET_ERROR)        //調用listen()函數將套接字置入監聽模式並准備接受連接請求,參數(已捆綁未連接的套接字描述字,正在等待連接的最大隊列長度)
    { 
        printf("Listen fail!\n");  
        closesocket(sock);  
        WSACleanup();  
        exit(1);  
    }  

    SOCKET msgsock;            //創建一個新的套接字(用於接收accept函數的返回值,即表示已經接受的那個客戶端的連接,進而接收Client發來的數據)
    char buf[BUFFER_SIZE];  //數據接收緩沖區
    while(1)  
    {  
        if((msgsock=accept(sock,(LPSOCKADDR)0,(int *)0))==INVALID_SOCKET)  //進入監聽狀態后,調用accept()函數接收客戶端的連接請求,並把連接傳給msgsock套接字,原sock套接字繼續監聽其他客戶機連接請求
        {  
            printf("Accept fail!\n");  
            continue;  
        }  
        memset(buf,0,sizeof(buf));                                            //初始化數據接收緩沖區
        recv(msgsock,buf,BUFFER_SIZE,0);                                    //接收客戶端發送過來的數據  
        if(buf[0]=='e' && buf[1]=='x' && buf[2]=='i' && buf[3]=='t')        //"exit"命令,退出程序
        {  
            printf("The End.\n");  
            break;  
        }
        printf("C:\\Socket\\Server>%s",buf);  
        closesocket(msgsock);  
    }  

    closesocket(sock); //關閉套接字  
    WSACleanup();       //終止對Winsock DLL的使用,並釋放資源
    return 0;
}   
View Code

客戶端代碼(Client)

#include <winsock2.h>  
#include <stdio.h>  
#pragma comment(lib,"ws2_32.lib")    //把ws2_32.lib加到Link頁的連接庫  
//#define IP "172.18.68.243"            //在兩台計算機上測試,IP為Server端的IP地址  
#define IP "127.0.0.1"                //在一台計算機上測試,IP為本地回送地址
#define PORT 15001                    //注意:客戶端設置通信的端口 = 服務端的端口
#define BUFFER_SIZE 1024            //數據發送緩沖區大小

int main()  
{  
    char buf[BUFFER_SIZE];                                //buf數組存放客戶端發送的消息  
    int inputLen;                                        //用於輸入字符自增變量
    while(1)  
    {  
        printf("C:\\Socket\\Client>");  
        inputLen=0;  
        memset(buf,0,sizeof(buf));  
        while((buf[inputLen++]=getchar())!='\n')        //輸入以回車鍵為結束標識
        {
            ;
        }
        if(buf[0]=='e' && buf[1]=='x' && buf[2]=='i' && buf[3]=='t')  
        {  
            printf("The End.\n");  
            break;   
        }  

        WSADATA WSAData;  
        if(WSAStartup(MAKEWORD(2,0),&WSAData)==SOCKET_ERROR)  //WSAStartup()函數對Winsock DLL進行初始化
        {  
            printf("Socket initialize fail!\n");  
            continue;  
        }  
        SOCKET sock;                                            //客戶端進程創建套接字
        if((sock=socket(AF_INET,SOCK_STREAM,0))==SOCKET_ERROR)  //創建流套接字(與服務端保持一致)
        {  
            printf("Socket create fail!\n");  
            WSACleanup();  
            continue;  
        }  

        struct sockaddr_in ClientAddr;                //sockaddr_in結構用來標識TCP/IP協議下的地址,可強制轉換為sockaddr結構
        ClientAddr.sin_family=AF_INET;                //指Internet域
        ClientAddr.sin_port=htons(PORT);            //指定服務端所預留的端口
        ClientAddr.sin_addr.s_addr=inet_addr(IP);    //指定服務端所綁定的IP地址
        if(connect(sock,(LPSOCKADDR)&ClientAddr,sizeof(ClientAddr))==SOCKET_ERROR)  //調用connect()函數,向服務器進程發出連接請求  
        { 
            printf("Connect fail!\n");  
            closesocket(sock);  
            WSACleanup();  
            continue;  
        }  
        send(sock,buf,BUFFER_SIZE,0);                 //向服務器發送數據 
        closesocket(sock);                             //關閉套接字
        WSACleanup();                                //終止對Winsock DLL的使用,並釋放資源,以備下一次使用
    }  
    return 0;
}  
View Code

轉載:https://blog.csdn.net/lynch0571

實現Socket雙工通信案例

服務端代碼(Server)

#include <stdio.h>
#include <Winsock2.h> //Socket的函數調用 
#include <windows.h>

#define BUF_SIZE 6400  //  緩沖區大小

#pragma comment (lib, "ws2_32")     // 使用WINSOCK2.H時,則需要庫文件WS2_32.LIB

DWORD WINAPI Rcv(LPVOID lpParam)
{
    SOCKET sClient = *(SOCKET*)lpParam;
    int retVal;
    char bufRecv[BUF_SIZE];
    memset(bufRecv, 0, sizeof(bufRecv));
    while (1)
    {
        retVal = recv(sClient, bufRecv, BUF_SIZE, 0);
        if (retVal == SOCKET_ERROR) {
            printf("recive faild!\n");
            break;
        }
        else {
            printf("收到客戶端消息:%s\n", bufRecv);
        }
    }
    return 0;
}

DWORD WINAPI Snd(LPVOID lpParam)
{
    SOCKET sClient = *(SOCKET*)lpParam;
    int retVal;
    char bufSend[BUF_SIZE];
    memset(bufSend, 0, sizeof(bufSend));
    while (1)
    {
        gets(bufSend);
        retVal = send(sClient, bufSend, strlen(bufSend) + sizeof(char), 0);
        if (retVal == SOCKET_ERROR) {
            printf("send faild!\n");
            break;
        }
    }
    return 0;
}


int main(int argc, char* argv[])
{
    // 初始化套接字動態庫
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        printf("winsock load faild!\n");
        return 1;
    }

    //  創建服務段套接字
    SOCKET sServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sServer == INVALID_SOCKET) {
        printf("socket faild!\n");
        WSACleanup();
        return -1;
    }

    //  服務端地址
    sockaddr_in addrServ;

    addrServ.sin_family = AF_INET;
    addrServ.sin_port = htons(9999);
    addrServ.sin_addr.s_addr = htonl(INADDR_ANY);

    //  綁定套接字
    if (bind(sServer, (const struct sockaddr*)&addrServ, sizeof(addrServ)) == SOCKET_ERROR) {
        printf("bind faild!\n");
        closesocket(sServer);
        WSACleanup();
        return -1;
    }

    printf("Server is On IP:[%s],port:[%d]\n", inet_ntoa(addrServ.sin_addr), ntohs(addrServ.sin_port));

    //  監聽套接字  數字表示最多能監聽客戶個數
    if (listen(sServer, 5) == SOCKET_ERROR) {
        printf("listen faild!\n");
        closesocket(sServer);
        WSACleanup();
        return -1;
    }

    SOCKET sClient; //  客戶端套接字

    sockaddr_in addrClient;
    int addrClientLen = sizeof(addrClient);


    sClient = accept(sServer, (sockaddr FAR*)&addrClient, &addrClientLen);
    if (sClient == INVALID_SOCKET) {
        printf("accept faild!\n");
        closesocket(sServer);
        WSACleanup();
        return -1;
    }
    printf("accepted client IP:[%s],port:[%d]\n", inet_ntoa(addrClient.sin_addr), ntohs(addrClient.sin_port));

    HANDLE hThread1, hThread2;
    DWORD dwThreadId1, dwThreadId2;

    hThread1 = ::CreateThread(NULL, NULL, Snd, (LPVOID*)&sClient, 0, &dwThreadId1);
    hThread2 = ::CreateThread(NULL, NULL, Rcv, (LPVOID*)&sClient, 0, &dwThreadId2);

    ::WaitForSingleObject(hThread1, INFINITE);
    ::WaitForSingleObject(hThread2, INFINITE);
    ::CloseHandle(hThread1);
    ::CloseHandle(hThread2);

    closesocket(sClient);
    WSACleanup(); // 資源釋放

    return 0;
}
View Code

客戶端代碼(Client)

#include <stdio.h>
#include <Winsock2.h> //Socket的函數調用 
#include <windows.h>

#define BUF_SIZE 6400

#pragma comment (lib, "ws2_32")     // 使用WINSOCK2.H時,則需要庫文件WS2_32.LIB

DWORD WINAPI Rcv(LPVOID lpParam)
{
    SOCKET sHost = *(SOCKET*)lpParam;
    int retVal;
    char bufRecv[BUF_SIZE];
    memset(bufRecv, 0, sizeof(bufRecv));
    while (1)
    {
        retVal = recv(sHost, bufRecv, BUF_SIZE, 0);
        if (retVal == SOCKET_ERROR) {
            printf("recive faild!\n");
            break;
        }
        else {
            printf("收到服務器消息:%s\n", bufRecv);
        }
    }
    return 0;
}

DWORD WINAPI Snd(LPVOID lpParam)
{
    SOCKET sHost = *(SOCKET*)lpParam;
    int retVal;
    char bufSend[BUF_SIZE];
    memset(bufSend, 0, sizeof(bufSend));
    while (1)
    {
        gets(bufSend);
        retVal = send(sHost, bufSend, strlen(bufSend) + sizeof(char), 0);
        if (retVal == SOCKET_ERROR) {
            printf("send faild!\n");
            break;
        }
    }
    return 0;
}

int main(int argc, char* argv[])
{
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        printf("Winsock load faild!\n");
        return 1;
    }

    //  服務器套接字
    SOCKET sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sHost == INVALID_SOCKET) {
        printf("socket faild!\n");
        WSACleanup();
        return -1;
    }

    SOCKADDR_IN servAddr;
    servAddr.sin_family = AF_INET;
    //  注意   當把客戶端程序發到別人的電腦時 此處IP需改為服務器所在電腦的IP
    servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    servAddr.sin_port = htons(9999);

    //  連接服務器
    if (connect(sHost, (LPSOCKADDR)&servAddr, sizeof(servAddr)) == SOCKET_ERROR) {
        printf("connect faild!\n");
        closesocket(sHost);
        WSACleanup();
        return -1;
    }
    printf("連接到服務器 IP:[%s],port:[%d]\n", inet_ntoa(servAddr.sin_addr), ntohs(servAddr.sin_port));

    HANDLE hThread1, hThread2;
    DWORD dwThreadId1, dwThreadId2;

    hThread1 = ::CreateThread(NULL, NULL, Snd, (LPVOID)&sHost, 0, &dwThreadId1);
    hThread2 = ::CreateThread(NULL, NULL, Rcv, (LPVOID)&sHost, 0, &dwThreadId2);

    ::WaitForSingleObject(hThread1, INFINITE);
    ::WaitForSingleObject(hThread2, INFINITE);
    ::CloseHandle(hThread1);
    ::CloseHandle(hThread2);


    closesocket(sHost);
    WSACleanup();
    return 0;
}
View Code

轉載:https://www.cnblogs.com/wuyepeng/

 

實現文件傳輸

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <WinSock2.h> 

#define PORT 8087 
#define SERVER_IP "127.0.0.1" 
#define BUFFER_SIZE 1024 
#define FILE_NAME_MAX_SIZE 512 
#pragma comment(lib, "WS2_32") 

int main()
{
    // 聲明並初始化一個服務端(本地)的地址結構 
    sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.S_un.S_addr = INADDR_ANY;
    server_addr.sin_port = htons(PORT);

    // 初始化socket dll 
    WSADATA wsaData;
    WORD socketVersion = MAKEWORD(2, 0);
    if (WSAStartup(socketVersion, &wsaData) != 0)
    {
        printf("Init socket dll error!");
        exit(1);
    }

    // 創建socket 
    SOCKET m_Socket = socket(AF_INET, SOCK_STREAM, 0);
    if (SOCKET_ERROR == m_Socket)
    {
        printf("Create Socket Error!");
        exit(1);
    }

    //綁定socket和服務端(本地)地址 
    if (SOCKET_ERROR == bind(m_Socket, (LPSOCKADDR)&server_addr, sizeof(server_addr)))
    {
        printf("Server Bind Failed: %d", WSAGetLastError());
        exit(1);
    }

    //監聽 
    if (SOCKET_ERROR == listen(m_Socket, 10))
    {
        printf("Server Listen Failed: %d", WSAGetLastError());
        exit(1);
    }


    while (1)
    {
        printf("Listening To Client...\n");

        sockaddr_in client_addr;
        int client_addr_len = sizeof(client_addr);

        SOCKET m_New_Socket = accept(m_Socket, (sockaddr *)&client_addr, &client_addr_len);
        if (SOCKET_ERROR == m_New_Socket)
        {
            printf("Server Accept Failed: %d", WSAGetLastError());
            break;
        }

        char buffer[BUFFER_SIZE];
        memset(buffer, 0, BUFFER_SIZE);
        if (recv(m_New_Socket, buffer, BUFFER_SIZE, 0) < 0)
        {
            printf("Server Receive Data Failed!");
            break;
        }

        char file_name[FILE_NAME_MAX_SIZE + 1];
        memset(file_name, 0, FILE_NAME_MAX_SIZE + 1);
        strncpy(file_name, buffer, strlen(buffer)>FILE_NAME_MAX_SIZE ? FILE_NAME_MAX_SIZE : strlen(buffer));
        printf("%s\n", file_name);

        FILE * fp = fopen(file_name, "rb"); //windows下是"rb",表示打開一個只讀的二進制文件 
        if (NULL == fp)
        {
            printf("File: %s Not Found\n", file_name);
        }
        else
        {
            memset(buffer, 0, BUFFER_SIZE);
            int length = 0;

            while ((length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0)
            {
                if (send(m_New_Socket, buffer, length, 0) < 0)
                {
                    printf("Send File: %s Failed\n", file_name);
                    break;
                }
                memset(buffer, 0, BUFFER_SIZE);
            }

            fclose(fp);
            printf("File: %s Transfer Successful!\n", file_name);
        }
        closesocket(m_New_Socket);
    }

    closesocket(m_Socket);
    //釋放winsock庫 
    WSACleanup();
    return 0;
}
View Code
/*************************************************************************
> File Name: Win_Client.c
> Author: SongLee
************************************************************************/

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <WinSock2.h> 

#define PORT 8087 
#define SERVER_IP "127.0.0.1" 
#define BUFFER_SIZE 1024 
#define FILE_NAME_MAX_SIZE 512 
#pragma comment(lib, "WS2_32") 

int main()
{
    // 初始化socket dll 
    WSADATA wsaData;
    WORD socketVersion = MAKEWORD(2, 0);
    if (WSAStartup(socketVersion, &wsaData) != 0)
    {
        printf("Init socket dll error!");
        exit(1);
    }

    //創建socket 
    SOCKET c_Socket = socket(AF_INET, SOCK_STREAM, 0);
    if (SOCKET_ERROR == c_Socket)
    {
        printf("Create Socket Error!");
        system("pause");
        exit(1);
    }

    //指定服務端的地址 
    sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.S_un.S_addr = inet_addr(SERVER_IP);
    server_addr.sin_port = htons(PORT);

    if (SOCKET_ERROR == connect(c_Socket, (LPSOCKADDR)&server_addr, sizeof(server_addr)))
    {
        printf("Can Not Connect To Server IP!\n");
        system("pause");
        exit(1);
    }

    //輸入文件名 
    char file_name[FILE_NAME_MAX_SIZE + 1];
    memset(file_name, 0, FILE_NAME_MAX_SIZE + 1);
    printf("Please Input File Name On Server: ");
    scanf("%s", &file_name);

    char buffer[BUFFER_SIZE];
    memset(buffer, 0, BUFFER_SIZE);
    strncpy(buffer, file_name, strlen(file_name)>BUFFER_SIZE ? BUFFER_SIZE : strlen(file_name));

    //向服務器發送文件名 
    if (send(c_Socket, buffer, BUFFER_SIZE, 0) < 0)
    {
        printf("Send File Name Failed\n");
        system("pause");
        exit(1);
    }

    //打開文件,准備寫入 
    FILE * fp = fopen(file_name, "wb"); //windows下是"wb",表示打開一個只寫的二進制文件 
    if (NULL == fp)
    {
        printf("File: %s Can Not Open To Write\n", file_name);
        system("pause");
        exit(1);
    }
    else
    {
        memset(buffer, 0, BUFFER_SIZE);
        int length = 0;
        while ((length = recv(c_Socket, buffer, BUFFER_SIZE, 0)) > 0)
        {
            if (fwrite(buffer, sizeof(char), length, fp) < length)
            {
                printf("File: %s Write Failed\n", file_name);
                break;
            }
            memset(buffer, 0, BUFFER_SIZE);
        }

        printf("Receive File: %s From Server Successful!\n", file_name);
    }

    fclose(fp);
    closesocket(c_Socket);

    //釋放winsock庫 
    WSACleanup();

    system("pause");
    return 0;
}
View Code

轉載:腳本之家

 

使用select

#include<stdlib.h>
#include<WINSOCK2.H>
#include <windows.h> 
#include <process.h>  

#include<iostream>
#include<string>
using namespace std;

#define BUF_SIZE 64
#pragma comment(lib,"WS2_32.lib")


void recv(PVOID pt)
{
    SOCKET  sHost = *((SOCKET *)pt);

    while (true)
    {
        char buf[BUF_SIZE];//清空接收數據的緩沖區
        memset(buf, 0, BUF_SIZE);
        int retVal = recv(sHost, buf, sizeof(buf), 0);
        if (SOCKET_ERROR == retVal)
        {
            int  err = WSAGetLastError();
            //無法立即完成非阻塞Socket上的操作
            if (err == WSAEWOULDBLOCK)
            {
                Sleep(1000);
                printf("\nwaiting  reply!");
                continue;
            }
            else if (err == WSAETIMEDOUT || err == WSAENETDOWN || err == WSAECONNRESET)//已建立連接
            {
                printf("\nrecv failed!");
                closesocket(sHost);
                WSACleanup();
                return;
            }

        }

        Sleep(100);

        printf("\n%s", buf);
        //break;
    }
}


int main()
{
    WSADATA wsd;
    SOCKET sHost;
    SOCKADDR_IN servAddr;//服務器地址
    int retVal;//調用Socket函數的返回值
    char buf[BUF_SIZE];
    //初始化Socket環境
    if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
    {
        printf("WSAStartup failed!\n");
        return -1;
    }
    sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    //設置服務器Socket地址
    servAddr.sin_family = AF_INET;
    servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    //在實際應用中,建議將服務器的IP地址和端口號保存在配置文件中
    servAddr.sin_port = htons(6000);
    //計算地址的長度
    int sServerAddlen = sizeof(servAddr);



    //調用ioctlsocket()將其設置為非阻塞模式
    int iMode = 1;
    retVal = ioctlsocket(sHost, FIONBIO, (u_long FAR*)&iMode);


    if (retVal == SOCKET_ERROR)
    {
        printf("ioctlsocket failed!");
        WSACleanup();
        return -1;
    }


    //循環等待
    while (true)
    {
        //連接到服務器
        retVal = connect(sHost, (LPSOCKADDR)&servAddr, sizeof(servAddr));
        if (SOCKET_ERROR == retVal)
        {
            int err = WSAGetLastError();
            //無法立即完成非阻塞Socket上的操作
            if (err == WSAEWOULDBLOCK || err == WSAEINVAL)
            {
                Sleep(1);
                printf("check  connect!\n");
                continue;
            }
            else if (err == WSAEISCONN)//已建立連接
            {
                break;
            }
            else
            {
                printf("connection failed!\n");
                closesocket(sHost);
                WSACleanup();
                return -1;
            }
        }
    }


    unsigned long     threadId = _beginthread(recv, 0, &sHost);//啟動一個線程接收數據的線程   



    while (true)
    {
        //向服務器發送字符串,並顯示反饋信息
        printf("input a string to send:\n");
        std::string str;
        //接收輸入的數據
        std::cin >> str;
        //將用戶輸入的數據復制到buf中
        ZeroMemory(buf, BUF_SIZE);
        strcpy(buf, str.c_str());
        if (strcmp(buf, "quit") == 0)
        {
            printf("quit!\n");
            break;
        }

        while (true)
        {
            retVal = send(sHost, buf, strlen(buf), 0);
            if (SOCKET_ERROR == retVal)
            {
                int err = WSAGetLastError();
                if (err == WSAEWOULDBLOCK)
                {
                    //無法立即完成非阻塞Socket上的操作
                    Sleep(5);
                    continue;
                }

                else
                {
                    printf("send failed!\n");
                    closesocket(sHost);
                    WSACleanup();
                    return -1;
                }
            }
            break;
        }


    }

    return 0;
}
View Code
#include <WinSock2.h>  
#include <Windows.h>  
#include <MSWSock.h>  
#include <stdio.h>  
#include <map>  
using namespace std;


#pragma comment(lib,"Ws2_32.lib")  
#pragma comment(lib,"Mswsock.lib")  


int main()
{
    WSAData wsaData;
    if (0 != WSAStartup(MAKEWORD(2, 2), &wsaData))
    {
        printf("初始化失敗!%d\n", WSAGetLastError());
        Sleep(5000);
        return -1;
    }

    USHORT nport = 6000;
    SOCKET sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    u_long ul = 1;
    ioctlsocket(sListen, FIONBIO, &ul);

    sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(nport);
    sin.sin_addr.S_un.S_addr = ADDR_ANY;


    if (SOCKET_ERROR == bind(sListen, (sockaddr*)&sin, sizeof(sin)))
    {
        printf("bind failed!%d\n", WSAGetLastError());
        Sleep(5000);
        return -1;
    }


    listen(sListen, 5);


    //1)初始化一個套接字集合fdSocket,並將監聽套接字放入  
    fd_set socketSet;
    FD_ZERO(&socketSet);
    FD_SET(sListen, &socketSet);

    TIMEVAL time = { 1, 0 };
    char buf[4096];


    fd_set    readSet;
    FD_ZERO(&readSet);

    fd_set    writeSet;
    FD_ZERO(&readSet);


    while (true)
    {
        //2)將fdSocket的一個拷貝fdRead傳給select函數  
        readSet = socketSet;
        writeSet = socketSet;

        //同時檢查套接字的可讀可寫性。
        int   nRetAll = select(0, &readSet, &writeSet, NULL, NULL/*&time*/);//若不設置超時則select為阻塞  
        if (nRetAll >0)   //-1
        {
            //是否存在客戶端的連接請求。  
            if (FD_ISSET(sListen, &readSet))//在readset中會返回已經調用過listen的套接字。  
            {

                if (socketSet.fd_count < FD_SETSIZE)
                {
                    sockaddr_in addrRemote;
                    int nAddrLen = sizeof(addrRemote);
                    SOCKET sClient = accept(sListen, (sockaddr*)&addrRemote, &nAddrLen);
                    if (sClient != INVALID_SOCKET)
                    {
                        FD_SET(sClient, &socketSet);
                        printf("\n接收到連接:(%s)", inet_ntoa(addrRemote.sin_addr));
                    }
                }
                else
                {
                    printf("連接數量已達上限!\n");
                    continue;
                }
            }


            for (int i = 0; i<socketSet.fd_count; i++)
            {
                if (FD_ISSET(socketSet.fd_array[i], &readSet))
                {
                    //調用recv,接收數據。 
                    int nRecv = recv(socketSet.fd_array[i], buf, 4096, 0);
                    if (nRecv > 0)
                    {
                        buf[nRecv] = 0;
                        printf("\nrecv  %d :  %s", socketSet.fd_array[i], buf);
                    }
                }

                if (FD_ISSET(socketSet.fd_array[i], &writeSet))
                {

                    //調用send,發送數據。
                    char buf[] = "hello!";
                    int nRet = send(socketSet.fd_array[i], buf, strlen(buf) + 1, 0);
                    if (nRet <= 0)
                    {
                        if (GetLastError() == WSAEWOULDBLOCK)
                        {
                            //do nothing  
                        }
                        else
                        {
                            closesocket(socketSet.fd_array[i]);
                            FD_CLR(socketSet.fd_array[i], &socketSet);
                        }
                    }
                    else
                    {
                        printf("\nsend  hello!");
                    }
                }
            }

        }
        else if (nRetAll == 0)
        {
            printf("time out!\n");
        }
        else
        {
            printf("select error!%d\n", WSAGetLastError());
            Sleep(5000);
            break;
        }

        Sleep(1000);

    }
    closesocket(sListen);
    WSACleanup();
}
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM