WINDOWS C: TCP Socket send&recv 同时发送和接收



我正在尝试通过Windows上的服务器和客户端之间的TCP套接字进行双向通信。 我尝试过使用线程,但它不起作用,我不知道为什么。

如果我尝试将其放入while循环中,它会等待用户键入某些内容(因为fgets()(,然后再打印下一条消息。

while(1) {
        bzero(message, 2000);
        if (recv(sock, message, 2000, 0) < 0) {
            printf("Connection lost!n");
            getch();
        }
        else {
            strcat(message, "");
            fprintf(stdout, "%s", message);
        };
        bzero(client, 2000);
        fgets(sednmesg, sizeof(sednmesg), stdin);
        strcat(client, sednmesg);
        strcat(client, "");
        send(sock, client, strlen(client), 0);
}

我对线程的灾难性尝试:

服务器.c:

#include <stdio.h>
#include <winsock.h>
#include <stdlib.h>
#include "stdafx.h"
#include <conio.h>
#include <io.h>
#define bzero(b,len) (memset((b), '', (len)), (void) 0)  
#pragma comment(lib,"ws2_32.lib") //Winsock Library
char message[4040];
DWORD WINAPI thrd() {
    WSADATA wsa;
    SOCKET sock, newsock;
    int c;
    struct sockaddr_in server, client;
    char smesg[155];
    printf("nInitialising Winsock...");
    if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
    {
        printf("Failed. Error Code : %d", WSAGetLastError());
        return 1;
    }
    printf("Initialised.n");
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
        printf("Could not create socket! Error: %d", WSAGetLastError());
        return 1;
    }
    //textcolor(2);
    printf("Socket Created!n");
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons(8989);
    //bind
    if (bind(sock, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) {
        printf("Bind failed! Error Code: %d", WSAGetLastError());
    }
    puts("Binded!");
    printf("nNow Listening...n");
    listen(sock, 1);
    //Accept!
    c = sizeof(struct sockaddr_in);
    newsock = accept(sock, (struct sockaddr *)&client, &c);
    if (newsock == INVALID_SOCKET) {
        printf("Couldn't Accept connection!");
    }
    printf("Accepted Connection!n");
    u_long iMode = 1;
    ioctlsocket(newsock, FIONBIO, &iMode);
    Sleep(99);
    system("cls");
    printf("Writer Thread has been started!");
    //char *client_ip = inet_ntoa(client.sin_addr);
    //int client_port = ntohs(client.sin_port);
    while (1) {
        bzero(smesg, sizeof(smesg));
        fgets(smesg, sizeof(smesg), stdin);
        strcat(smesg, "");
        send(newsock, smesg, strlen(smesg), 0);
    }
}
int main()
{
    WSADATA wsa;
    FILE * fp;
    unsigned long on = 1;
    const char *file = "fout.txt";
    SOCKET sock, newsock;
    int c;
    struct sockaddr_in server, client;
    char smesg[155];
    printf("nInitialising Winsock...");
    if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
    {
        printf("Failed. Error Code : %d", WSAGetLastError());
        return 1;
    }
    printf("Initialised.n");
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
        printf("Could not create socket! Error: %d", WSAGetLastError());
        return 1;
    }
    //textcolor(2);
    printf("Socket Created!n");
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons(3939);
    //bind
    if (bind(sock, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) {
        printf("Bind failed! Error Code: %d", WSAGetLastError());
    }
    puts("Binded!");
    printf("nNow Listening...n");
    listen(sock, 1);
    //Accept!
    c = sizeof(struct sockaddr_in);
    newsock = accept(sock, (struct sockaddr *)&client, &c);
    ioctlsocket(newsock, FIONBIO, &on);
    if (newsock == INVALID_SOCKET) {
        printf("Couldn't Accept connection!");
    }
    printf("Accepted Connection!n");
        //char *client_ip = inet_ntoa(client.sin_addr);
        //int client_port = ntohs(client.sin_port);
    HANDLE thread = CreateThread(NULL, 0, thrd, NULL, 0, NULL);
    fp = fopen(file, "r+");
        while (1) {
            /*
            bzero(smesg, sizeof(smesg));
            printf("Command: ");
            fgets(smesg, 155, stdin);
            strcat(smesg, "");
            send(newsock, smesg, strlen(smesg), 0);
            */
            bzero(message, sizeof(message));
            recv(newsock, message, 2000, 0);
            fprintf(stdout, "%s", message);
            fprintf(fp, "%s", message);
        }
        fclose(fp);
    return 0;
}

客户网:

#include <stdio.h>
#include <winsock.h>
#include <stdlib.h>
#include "stdafx.h"
#include <conio.h>
#define bzero(b,len) (memset((b), '', (len)), (void) 0)  
#pragma comment(lib,"ws2_32.lib") //Winsock Library
DWORD WINAPI thrd() {
    char client[2050] = "Client: ";
    WSADATA wsa;
    SOCKET sock;
    struct sockaddr_in server;
    char sednmesg[2000];
    printf("nInitialising Winsock...");
    if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
    {
        printf("Failed. Error Code : %d", WSAGetLastError());
        getch();
        return 1;
    }
    printf("Initialised.n");

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
        printf("Could not create socket! Error: %d", WSAGetLastError());
        getch();
        return 1;
    }
    //textcolor(2);
    printf("Socket Created!n");
    //ioctlsocket(sock, FIONBIO, &on);
    server.sin_addr.s_addr = inet_addr("127.0.0.1");
    server.sin_family = AF_INET;
    server.sin_port = htons(8989);
    //Connect
    if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0) {
        puts("Connect Error");
        getch();
        return 1;
    }
    puts("Connectedn");
    // If iMode!=0, non-blocking mode is enabled.
    u_long iMode = 1;
    ioctlsocket(sock, FIONBIO, &iMode);
    Sleep(99);
    system("cls");
    printf("Writer Thread has been started!");
    //We'll be running this one on port 8989 if this doesn't work!
    while (1) {
        bzero(client, 2000);
        fgets(sednmesg, sizeof(sednmesg), stdin);
        strcat(client, sednmesg);
        strcat(client, "");
        send(sock, client, strlen(client), 0);
    }
}
int main(int argc, char *argv[])
{
    char *msg = "a";
    char client[2050] = "Client: ";
    unsigned long on = 1;
    int reader;
    WSADATA wsa;
    int sent = 0;
    SOCKET sock;
    struct sockaddr_in server;
    char message[2000];
    char sednmesg[2000];
    printf("nInitialising Winsock...");
    if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
    {
        printf("Failed. Error Code : %d", WSAGetLastError());
        getch();
        return 1;
    }
    printf("Initialised.n");

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
        printf("Could not create socket! Error: %d", WSAGetLastError());
        getch();
        return 1;
    }
    //textcolor(2);
    printf("Socket Created!n");
    //ioctlsocket(sock, FIONBIO, &on);
    server.sin_addr.s_addr = inet_addr("127.0.0.1");
    server.sin_family = AF_INET;
    server.sin_port = htons(3939);
    //Connect
    if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0) {
        puts("Connect Error");
        getch();
        return 1;
    }
    puts("Connectedn");
    // If iMode!=0, non-blocking mode is enabled.
    u_long iMode = 1;
    ioctlsocket(sock, FIONBIO, &iMode);
    //Creating writer thread.
    HANDLE thread = CreateThread(NULL, 0, thrd, NULL, 0, NULL);
    while (1) {
        bzero(message, 2000);
        if (recv(sock, message, 2000, 0) < 0) {
            printf("Connection lost!n");
            getch();
        }
        else {
            strcat(message, "");
            fprintf(stdout, "%s", message);
        };
        //bzero(client, 2000);
        /*
        fgets(sednmesg, sizeof(sednmesg), stdin);
        strcat(client, sednmesg);
        strcat(client, "");
        send(sock, client, strlen(client), 0);
        */
    }
    return 0;
}

您无需打开/连接 2 个单独的侦听端口即可实现双向通信。 TCP是双向的,你只需要一个连接。 但是,您在两端都启用了非阻塞套接字 I/O,但实际上并没有正确使用非阻塞 I/O。特别是,您根本不处理WSAEWOULDBLOCK错误代码,当没有数据可供读取时,recv()会报告该错误代码,当接收方有太多数据要读取且尚未接收新数据时,send()会报告该错误代码。

如果要使用线程,请使用单独的线程进行读取和发送,并完全忘记非阻塞 I/O。 但请确保您正确定义了线程(线程过程缺少必需的输入参数!

尝试更多类似的东西:

服务器.c:

#include "stdafx.h"
#include <stdio.h>
#include <winsock.h>
#include <stdlib.h>
#include <conio.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
DWORD WINAPI sendThrd(LPVOID lpParam)
{
    SOCKET sock = * (SOCKET*) lpParam;
    char smesg[155], *pdata;
    int len, ret;
    do
    {
        if (!fgets(smesg, sizeof(smesg), stdin))
            break;
        len = strlen(smesg);
        pdata = smesg;
        while (len > 0)
        {
            ret = send(sock, pdata, len, 0);
            if (ret == SOCKET_ERROR)
            {
                printf("Send failed. Error: %d", WSAGetLastError());
                break;
            }
            pdata += ret;
            len -= ret;
        }
    }
    while (true);
    shutdown(sock, SD_SEND);
    return 0;
}
DWORD WINAPI recvThrd(LPVOID lpParam)
{
    SOCKET sock = * (SOCKET*) lpParam;
    char smesg[256];
    int ret;
    FILE *fp = fopen("fout.txt", "w+");
    do
    {
        ret = recv(sock, smesg, sizeof(smesg), 0);
        if (ret <= 0)
        {
            if (ret == 0)
                printf("Client disconnectedn");
            else
                printf("Connection lost! Error: %dn", WSAGetLastError());
            break;
        }
        printf("%.*s", ret, smesg);
        if (fp)
            fprintf(fp, "%.*s", ret, smesg);        
    }
    while (true);
    if (fp)
        fclose(fp);
    shutdown(sock, SD_RECEIVE);
    return 0;
}
int main()
{
    WSADATA wsa;
    SOCKET sock, newsock;
    int c;
    struct sockaddr_in server;
    printf("Initializing Winsock...n");
    int ret = WSAStartup(MAKEWORD(2, 2), &wsa);
    if (ret != 0)
    {
        printf("Initialization Failed. Error: %d", ret);
        return 1;
    }
    printf("Initialized.n");
    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock == INVALID_SOCKET) {
        printf("Could not create socket! Error: %dn", WSAGetLastError());
        return 1;
    }
    //textcolor(2);
    printf("Socket Created!n");
    memset(&server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons(3939);
    //bind
    if (bind(sock, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) {
        printf("Bind failed! Error: %dn", WSAGetLastError());
        closesocket(sock);
        return 1;
    }
    printf("Binded!n");
    // listen
    if (listen(sock, 1) == SOCKET_ERROR) {
        printf("Listen failed! Error: %dn", WSAGetLastError());
        closesocket(sock);
        return 1;
    }
    printf("Now Listening...n");
    //Accept!
    c = sizeof(client);
    newsock = accept(sock, (struct sockaddr *)&client, &c);
    if (newsock == INVALID_SOCKET) {
        printf("Couldn't Accept connection! Error: %dn", WSAGetLastError());
        closesocket(sock);
        return 1;
    }
    //char *client_ip = inet_ntoa(client.sin_addr);
    //int client_port = ntohs(client.sin_port);
    printf("Accepted Connection!n");
    printf("Starting Reader/Writer Threads...n");
    HANDLE threads[2];
    threads[0] = CreateThread(NULL, 0, sendThrd, &newsock, 0, NULL);
    threads[1] = CreateThread(NULL, 0, recvThrd, &newsock, 0, NULL);
    WaitForMultipleObjects(2, threads, TRUE, INFINITE);
    CloseHandle(threads[0]);
    CloseHandle(threads[1]);
    closesocket(newsock);
    closesocket(sock);
    return 0;
}

客户网:

#include "stdafx.h"
#include <stdio.h>
#include <winsock.h>
#include <stdlib.h>
#include <conio.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
DWORD WINAPI sendThrd(LPVOID lpParam)
{
    SOCKET sock = * (SOCKET*) lpParam;
    char smesg[155], *pdata;
    int len, ret;
    do
    {
        if (!fgets(smesg, sizeof(smesg), stdin))
            break;
        len = strlen(smesg);
        pdata = smesg;
        while (len > 0)
        {
            ret = send(sock, pdata, len, 0);
            if (ret == SOCKET_ERROR)
            {
                printf("Send failed. Error: %dn", WSAGetLastError());
                break;
            }
            pdata += ret;
            len -= ret;
        }
    }
    while (true);
    shutdown(sock, SD_SEND);
    return 0;
}
DWORD WINAPI recvThrd(LPVOID lpParam)
{
    SOCKET sock = * (SOCKET*) lpParam;
    char smesg[256];
    int ret;
    do
    {
        ret = recv(sock, smesg, sizeof(smesg), 0);
        if (ret <= 0)
        {
            if (ret == 0)
                printf("Server disconnectedn");
            else
                printf("Connection lost! Error: %dn", WSAGetLastError());
            break;
        }
        printf("%.*s", ret, smesg);
    }
    while (true);
    shutdown(sock, SD_RECEIVE);
    return 0;
}
int main(int argc, char *argv[])
{
    WSADATA wsa;
    SOCKET sock;
    struct sockaddr_in server;
    printf("Initializing Winsock...n");
    int ret = WSAStartup(MAKEWORD(2, 2), &wsa);
    if (ret != 0)
    {
        printf("Initialization Failed. Error: %d", ret);
        return 1;
    }
    printf("Initialized.n");
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == INVALID_SOCKET) {
        printf("Could not create socket! Error: %d", WSAGetLastError());
        getch();
        return 1;
    }
    //textcolor(2);
    printf("Socket Created!n");
    memset(&server, 0, sizeof(server));
    server.sin_addr.s_addr = inet_addr("127.0.0.1");
    server.sin_family = AF_INET;
    server.sin_port = htons(3939);
    //Connect
    if (connect(sock, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) {
        printf("Connect failed! Error: %d", WSAGetLastError());
        closesocket(sock);
        getch();
        return 1;
    }
    printf("Connectedn");
    //Creating reader/writer threads.
    printf("Starting Reader/Writer Threads...n");
    HANDLE threads[2];
    threads[0] = CreateThread(NULL, 0, sendThrd, &sock, 0, NULL);
    threads[1] = CreateThread(NULL, 0, recvThrd, &sock, 0, NULL);
    WaitForMultipleObjects(2, threads, TRUE, INFINITE);
    CloseHandle(threads[0]);
    CloseHandle(threads[1]);
    closesocket(sock);
    getch();
    return 0;
}

最新更新