2017-04-08 4 views
0

Ich versuche, bidirektionale Kommunikation über einen TCP-Socket zwischen Server und Client unter Windows zu machen. Ich habe versucht, Threads zu verwenden, aber es funktioniert nicht, und ich weiß nicht warum.WINDOWS C: TCP-Socket send & recv zur gleichen Zeit

Wenn ich versuche, dies in die while-Schleife zu setzen, wartet es, dass der Benutzer etwas (wegen fgets()) eingibt, bevor es die nächste Nachricht druckt.

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

     fgets(sednmesg, sizeof(sednmesg), stdin); 
     strcat(client, sednmesg); 
     strcat(client, "\0"); 
     send(sock, client, strlen(client), 0); 
} 

Mein katastrophalen Versuch mit Themen:

server.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), '\0', (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, "\0"); 
     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, "\0"); 
      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; 
} 

client.c:

#include <stdio.h> 
#include <winsock.h> 
#include <stdlib.h> 
#include "stdafx.h" 
#include <conio.h> 

#define bzero(b,len) (memset((b), '\0', (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("Connected\n"); 
    // 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, "\0"); 
     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("Connected\n"); 
    // 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, "\0"); 
      fprintf(stdout, "%s", message); 
     }; 
     //bzero(client, 2000); 
     /* 
     fgets(sednmesg, sizeof(sednmesg), stdin); 
     strcat(client, sednmesg); 
     strcat(client, "\0"); 
     send(sock, client, strlen(client), 0); 
     */ 
    } 
    return 0; 
} 
+2

Nämlich: Nicht richtig und vollständig das Ergebnis Griff von recv zurück (). Fehler beim Streaming von TCP. Missbrauch von C-String-Aufrufen, die einen NUL-Terminator erfordern. Verwendung des Cargo-Kult bzero() Cycle-Waster. – ThingyWotsit

+1

Warum öffnet Ihr Server zwei Überwachungsports und Ihr Client stellt eine Verbindung zu zwei Überwachungsports her? Sie benötigen nicht mehrere Ports für die bidirektionale Kommunikation. –

Antwort

0

Sie brauchen nicht zu öffnen/schließen Sie 2 separate Listening-Ports, um bidirektionale Kommunikation zu implementieren. TCP ist bidirektional, Sie benötigen nur eine Verbindung. Sie aktivieren jedoch nicht blockierende Socket-E/A an beiden Enden, aber Sie verwenden nicht tatsächlich nicht blockierende E/A richtig. Insbesondere behandeln Sie den WSAEWOULDBLOCK Fehlercode überhaupt nicht, der von recv() gemeldet wird, wenn keine Daten zum Lesen verfügbar sind, und send(), wenn der Empfänger zu viele Daten zum Lesen hat und keine neuen Daten empfangen kann.

Wenn Sie Threads verwenden möchten, verwenden Sie separate Threads zum Lesen und Senden und vergessen Sie nicht blockierende E/A. Stellen Sie jedoch sicher, dass Sie Ihre Threads korrekt definieren (in der Thread-Prozedur fehlt ein erforderlicher Eingabeparameter!).

etwas mehr wie die Sie interessieren:

server.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 disconnected\n"); 
      else 
       printf("Connection lost! Error: %d\n", 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: %d\n", 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: %d\n", WSAGetLastError()); 
     closesocket(sock); 
     return 1; 
    } 
    printf("Binded!\n"); 

    // listen 
    if (listen(sock, 1) == SOCKET_ERROR) { 
     printf("Listen failed! Error: %d\n", 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: %d\n", 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; 
} 

client.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\n", 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 disconnected\n"); 
      else 
       printf("Connection lost! Error: %d\n", 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("Connected\n"); 

    //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; 
}