使用套接字发送/接收字符串

时间:2015-12-22 18:32:37

标签: c string sockets

这是一个简单的代码tcp客户端/服务器,服务器在建立连接后发送“Hello from Server”。我的问题是:

1)客户端在关闭server.exe窗口后写入字符串并且不知道原因;

2)客户端打印奇怪的字符而不是“来自服务器的Hello”。我错过了输出格式的东西。

SERVER

#if defined WIN32
#include <winsock2.h>
#else
#define closesocket close
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>

#define PROTOPORT 5193 //default protocol port number
#define QLEN 6 // size of request queue
#define BUFFERSIZE  10

void ErrorHandler (char *errorMessage) {
printf (errorMessage);
}

void ClearWinSock() {
#if defined WIN32
    WSACleanup ();
#endif
}


int main(void) {
#if defined WIN32

WSADATA wsaData;
int iResult = WSAStartup (MAKEWORD(2,2), &wsaData);

if (iResult != 0) {
    ErrorHandler ("Error at WSAStartup()\n");
    return 0;
}
#endif

// CREAZIONE DELLA SOCKET
int MySocket;
MySocket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (MySocket < 0) {
    ErrorHandler ("socket creation failed.\n");
    ClearWinSock();
    return 0;
}

// ASSEGNAZIONE DI UN INDIRIZZO ALLA SOCKET
struct sockaddr_in sad;
memset (&sad, 0, sizeof (sad)); //ensures that extra bytes contain 0
sad.sin_family = AF_INET;
sad.sin_addr.s_addr = inet_addr ("127.0.0.1"); //ip del server con conversione
                                               //da notazione dotted-decimal in un numero  a 32 bit
                                               //espresso nella rappresentazione della rete
sad.sin_port = htons (5193); //host to network short


//Assegnazione porta e ip alla socket e verifica presenza di eventuali errori
if (bind (MySocket, (struct sockaddr*) & sad, sizeof (sad)) < 0) {
    ErrorHandler ("bind() failed.\n");
    closesocket (MySocket);
    ClearWinSock ();
    return 0;
}


// SETTAGGIO DELLA SOCKET ALL'ASCOLTO
if (listen (MySocket, QLEN) < 0) {
    ErrorHandler ("listen() failed.\n");
    closesocket (MySocket);
    ClearWinSock ();
    return 0;
}

// ACCETTARE UNA NUOVA CONNESSIONE - e creazione di una nuova socket per comunicare con il client
struct sockaddr_in cad; //structure for the client address
int clientSocket; // socket descriptor for the client
int clientLen; //the size of the client address
printf ("Waiting for a client to connect...");
while (1) {
    clientLen = sizeof (cad); //set the size of the client address
    if ((clientSocket = accept (MySocket, (struct sockaddr*) &cad, &clientLen)) < 0) {
        ErrorHandler ("accept() failed.\n");

        // CHIUSURA DELLA CONNESSIONE
        closesocket (MySocket);
        ClearWinSock ();
        return 0;
    }
    printf ("Handling client %s\n", inet_ntoa (cad.sin_addr));
}


char* inputString = "Hello from server"; // Stringa da inviare
int stringLen = strlen (inputString); // Determina la lunghezza

// INVIARE DATI AL CLIENT
if (send (clientSocket, inputString, stringLen, 0) != stringLen) {
    ErrorHandler ("send () sent a different number of bytes than expected");
    closesocket (clientSocket);
    ClearWinSock();
    system("pause");
    return 0;
}

closesocket(MySocket);
ClearWinSock ();
return 0;

}

客户端

#if defined WIN32
#include <winsock2.h>
#else
#define closesocket close
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>

#define BUFFERSIZE 20 // Dimensione buffer che riceve dati dal server
#define PROTOPORT 5193 // Numero di porta di default

void ErrorHandler (char *errorMessage) {
    printf (errorMessage);
}

void ClearWinSock () {
#if defined WIN32
    WSACleanup();
#endif
}

int main (void) {
#if defined WIN32

    WSADATA wsaData;
    int iResult = WSAStartup (MAKEWORD (2,2), &wsaData);

    if (iResult !=0) {
        printf ("error at WSASturtup\n");
        return 0;
        }

#endif

    // CREAZIONE DELLA SOCKET
    int Csocket;
    Csocket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (Csocket < 0) {
        ErrorHandler ("socket creation failed.\n");
        closesocket (Csocket);
        ClearWinSock ();
        return 0;
    }

// COSTRUZIONE DELL'INDIRIZZO DEL SERVER
    struct sockaddr_in sad;
    memset (&sad, 0, sizeof (sad));
    sad.sin_family = AF_INET;
    sad.sin_addr.s_addr = inet_addr ("127.0.0.1"); //ip del server con conversione
                                                   //da notazione dotted-decimal in un numero  a 32 bit
                                                   //espresso nella rappresentazione della rete
    sad.sin_port = htons (5193); // Server port

    //CONNESSIONE AL SERVER
    if (connect (Csocket, (struct sockaddr*) &sad, sizeof (sad)) < 0) {
        ErrorHandler ("Failed to connect.\n");
        closesocket (Csocket);
        ClearWinSock();
        return 0;
    }

char buf[BUFFERSIZE];
    recv (Csocket, buf, BUFFERSIZE - 1, 0);

    printf("Server scrive: %s\n",buf);

    // CHIUSURA DELLA CONNESSIONE
    closesocket (Csocket);
    ClearWinSock();
    printf ("\n");
    system ("pause");
    return 0;
}

最后:如果我要发送更多字符串,我是否要为每个字符串使用一个send()和一个recv()?

1 个答案:

答案 0 :(得分:1)

最大的问题是你没有突破服务器循环。这就是为什么在退出服务器之前,您在客户端上看不到任何内容的原因。程序终止时套接字关闭,因此客户端中的recv调用不再阻塞。此外,在客户端,您不会检查recv的返回值并打印垃圾邮件。

服务器修复:

while (1) {
    clientLen = sizeof (cad); //set the size of the client address
    if ((clientSocket = accept (MySocket, (struct sockaddr*) &cad, &clientLen)) < 0) {
        ....
    }
    printf ("Handling client %s\n", inet_ntoa (cad.sin_addr));
    break; // <- terminate loop,
           // or just get rid of the loop altogether as there
           // is no real need for it I can see
}

客户端修复:

int read = recv (Csocket, buf, BUFFERSIZE - 1, 0);
if (read <= 0) {
    // Not successful
}
else {
    buf[read] = 0;   // Add eos
    printf("%s", buf);
}