【问题标题】:sending/receiving/manipulating strings with sockets使用套接字发送/接收/操作字符串
【发布时间】:2015-12-27 22:17:20
【问题描述】:

我在服务器和客户端之间使用套接字发送和接收字符串时遇到了一点问题。在此代码中,首先服务器将“已建立连接(意大利语为“connessione avvenuta”)发送到客户端(将其打印在屏幕上),然后客户端扫描一个字符串并将其发送到服务器,服务器删除元音并将其发送再次给客户。 当我用客户端打印它时,奇怪的字符出现在字符串的末尾,我想是因为我没有很好地关闭它。如何做到这一点?

**SERVER SIDE**

#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>
#include <string.h>

#define BUFSIZE 30

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

int main(void) {

//---------------------------INIZIALIZZAZIONE WSADATA

#if defined WIN32

    WSADATA wsaData;
    int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0) {
        printf ("Error at WSAStartup");
        return 0;
    }

#endif

//-------------------------------CREAZIONE SOCKET

  int Mysocket;
  Mysocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (Mysocket < 0) {
      printf("socket creation failed\n");
      return 0;
  }

  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");
  sad.sin_port = htons (9888);

//------------------------ASSEGNAZIONE PORTA E IP ALLA SOCKET

if (bind(Mysocket, (struct sockaddr*) &sad, sizeof(sad)) <0) {
    printf ("bind() failed\n");
    closesocket(Mysocket);
    return 0;
}

//---------------------------SETTAGGIO SOCKET ALL'ASCOLTO

int qlen = 10;

if (listen (Mysocket, qlen) < 0) {

    printf("listen() failed\n");
    closesocket(Mysocket);
    return 0;
}

struct sockaddr_in cad;
int Csocket;
int clientlen;

//------------------------------ACCETTA LA CONNESSIONE

while (1) {

    printf("In attesa di un client con cui comunicare\n");
    memset(&cad, 0, sizeof(cad));
    clientlen = sizeof(cad);

    if((Csocket = accept(Mysocket, (struct sockaddr*) &cad, &clientlen)) < 0) {
        printf ("accept failed\n");
        closesocket(Mysocket);
        ClearWinSock();
        return 0;
        }

    printf("connesso con il client\n");


//---------------------------------------INVIO STRINGA AL CLIENT

    char* inputString = "connessione avvenuta";
    int stringlen = strlen(inputString);


    if (send(Csocket, inputString, stringlen, 0) != stringlen) {
        printf("client-send() sent a different number of bytes than expected");
        closesocket(Csocket);
        ClearWinSock();
        system ("pause");
        return 0;
    }


//-------------------------------------RICEZIONE STRINGA DAL CLIENT

    char str1[BUFSIZE+1]; char str1des[BUFSIZE+1];
    int i,j=0;

    //recv (Csocket, str1, BUFSIZE - 1, 0);

    int read = recv(Csocket, str1, BUFSIZE-1, 0); str1[read] = '\0';


//-------------------------------ELIMINAZIONE VOCALI DALLA STRINGA RICEVUTA

    for(i=0;i<=strlen(str1)+1;i++) {

        if(str1[i]=='a'||str1[i]=='e'||str1[i]=='i'||str1[i]=='o'||str1[i]=='u' ||str1[i]=='A'||str1[i]=='E'||str1[i]=='I'||str1[i]=='O'||str1[i]=='U')
                        str1[i]=' ';
                else
                        str1des[j++]=str1[i];
            }

            str1des[j]='\0';

//-----------------------------------INVIO STRINGA ELABORATA AL CLIENT

            if (send(Csocket, str1des, strlen(str1des), 0) != strlen(str1des)) {
                printf("client-send() sent a different number of bytes than expected");
                closesocket(Csocket);
                ClearWinSock();
                system ("pause");
                return 0;
            }

}

//------------------------------------------CHIUSURA CONNESSIONE

closesocket (Csocket);
ClearWinSock();
printf ("\n");
system ("pause");
return 0;

}

**CLIENT SIDE**

#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>
#include <string.h>

#define BUFSIZE 30

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

//-----------------------------INIZIALIZZAZIONE WSADATA

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 SOCKET

    int Csocket;

    Csocket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);

    if (Csocket < 0) {

    printf ("socket creation failed");
    closesocket (Csocket);
    ClearWinSock();
    return 0;
    }

 //--------------------------COSTRUZIONE INDIRIZZO 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");
   sad.sin_port = htons (9888);


//------------------------------CONNESSIONE AL SERVER

  if (connect(Csocket, (struct sockaddr*) &sad, sizeof(sad)) < 0) {
      printf ("failed to connect\n");
      closesocket (Csocket);
      ClearWinSock();
      return 0;
  }


//-----------------------------RICEZIONE DATI DAL SERVER

  char buf[BUFSIZE+1];

  int read = recv (Csocket, buf, BUFSIZE - 1, 0);

if (read <=0) {

    printf ("Qualcosa non và!\n");
}

else {
    buf[read+1] = '\0';
    printf("Server scrive: %s\n", buf);
}


//----------------------------INVIO PRIMA STRINGA AL SERVER

char str1[BUFSIZE+1]; int stringlen = strlen(str1);
printf ("inserisci prima stringa:\n");
scanf ("%s", str1);

if (send(Csocket, str1, stringlen, 0) != stringlen) {
    printf("client-send() sent a different number of bytes than expected");
    closesocket(Csocket);
    ClearWinSock();
    system ("pause");
    return 0;
}

//------------------------------RICEZIONE STRINGA ELABORATA DAL SERVER

char buf2[BUFSIZE+1];

  int read2 = recv (Csocket, buf2, BUFSIZE - 1, 0);

if (read2 <=0) {

    printf ("Qualcosa non và!\n");
}

else {
    buf2[read+1] = 0;
    printf("Server scrive: %s\n", buf2);
}

//---------------------------------------CHIUSURA CONNESSIONE

closesocket (Csocket);
ClearWinSock();
printf ("\n");
system ("pause");
return 0;

}

【问题讨论】:

  • 您没有为您的字符串发送终止 NUL 字符。也就是说,传递给服务器上所有send 调用的len 参数必须是stringlen+1
  • 另外,在客户端上,您正在设置int stringlen = sizeof(str1) 并将其用作len 参数到send。虽然这不会导致您描述的问题,但它确实发送了不必要的数据,因为sizeof(str1) 是整个缓冲区,包括实际字符串结束后的垃圾。
  • 另一个问题是您假设每个recv 将从单个send 中获取所有数据。这不是recv 的工作方式。它可以返回少于整个发送消息。所以recv 几乎总是在一个循环中调用,它检查是否收到了整个消息。来自recv man page:“接收调用通常会返回任何可用的数据,直到请求的数量,而不是等待收到请求的全部数量。”
  • 服务器代码:char str1[BUFSIZE]; recv(Csocket, str1, BUFSIZE-1, 0); for (i=0; i
  • @cm161 添加:int read = recv(Csocket, str1, BUFSIZE-1, 0); str1[read] = '\0' --- str1[BUFSIZE]='\0' 已删除 --- stringlen = strlen(str1) 已修复(删除 sizeof)。我需要在 send() 上解决什么问题?因为还是不行..

标签: c string sockets


【解决方案1】:

使用 TCP 协议,send() 和 recv() 不需要写入/读取参数中给定的长度。您需要检查返回值以了解在套接字上写入/读取了多少字节。

有两种简单的方法可以在套接字上发送/读取字符串:

  • 使用标题。
    在您在套接字上写入的数据包中,您在字符串之前包含了字符串大小。
    例如,如果你写“hello”,你将发送的数据包将是这样的:

    +---------+---------------+
    | uint8_t |字符[大小] |
    +----------------------------+
    | 0x5    | “你好”     |
    +---------+---------------+

    使用这种方法,当您在套接字上读取时,您首先读取标头(示例中为 1 个字节),然后读取 N 个字节以获得完整的字符串。
    不要忘记在字符串末尾添加“\0”。

  • 在字符串末尾包含“/0”。

    +------------------+
    |字符[大小 + 1] |
    +------------------+
    | “你好\0”     |
    +------------------+

    通过这种方式,你在套接字上读取,直到你得到一个 '\0'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-14
    • 2015-02-04
    • 1970-01-01
    相关资源
    最近更新 更多