Socket服务端返回多余字符及重复PuTTy标识问题求助
Socket服务端返回多余字符问题的修复方案
问题根源
- 未正确终止接收的字符串:网络传输的数据不会自动以
\0结尾,直接用strlen(buffer)会读取缓冲区中残留的旧数据,导致处理范围错误。 - 发送了整个缓冲区的冗余数据:
send(clientfd, buffer, sizeof(buffer), 0)会把256字节的缓冲区全部发送,包括有效字符后的垃圾数据。 - Telnet协议的额外报文干扰:PuTTy作为Telnet客户端,会发送终端协商的控制报文,这些数据被当作普通字符串处理后,就会出现奇怪的重复标识或字符。
修复后的代码
#include <io.h> #include <stdio.h> #include <winsock2.h> #include <string.h> #define MY_PORT 8989 #define MAXBUF 256 int main(int argc, char *argv[]){ WSADATA wsa; SOCKET sockfd ,clientfd; struct sockaddr_in self; char buffer[MAXBUF]; printf("\nInitialising Winsock..."); if (WSAStartup(MAKEWORD(2,2),&wsa) != 0){ printf("Failed. Error Code : %d",WSAGetLastError()); return 1; } printf("Initialised.\n"); if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ){ perror("Socket"); exit(errno); } printf("Socket created.\n"); self.sin_family = AF_INET; self.sin_port = htons(MY_PORT); self.sin_addr.s_addr = INADDR_ANY; if ((bind(sockfd, (struct sockaddr*)&self, sizeof(self)))!=0){ perror("socket--bind"); exit(errno); } puts("Bind done"); if ((listen(sockfd, 20))!=0){ perror("socket--listen"); exit(errno); } puts("Waiting for incoming connections..."); while (1){ struct sockaddr_in client_addr; int addrlen=sizeof(client_addr); clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &addrlen); // 接收数据,预留1字节空间放终止符 int length=recv(clientfd, buffer, MAXBUF-1, 0); if(length <=0){ close(clientfd); continue; } buffer[length] = '\0'; // 手动添加字符串终止符,核心修复点1 // 转小写 for(int i=0; buffer[i]!='\0'; i++){ if(buffer[i]>=65 && buffer[i]<=90){ buffer[i]= buffer[i]+32; } } // 反转字符串 int loop=0, len=strlen(buffer); char temp; len--; while (loop<len){ temp=buffer[loop]; buffer[loop]=buffer[len]; buffer[len]=temp; loop++; len--; } // 只发送有效字符串长度,核心修复点2 send(clientfd, buffer, strlen(buffer), 0); close(clientfd); } close(sockfd); WSACleanup(); return 0; }
关键修改说明
- 接收数据时预留1字节空间,手动添加
\0终止符,确保strlen能正确计算有效字符串长度,避免读取缓冲区残留的脏数据。 - 发送时使用
strlen(buffer)代替sizeof(buffer),只发送处理后的有效字符,避免冗余数据被发送。 - 增加
recv返回值判断,接收失败时直接关闭连接,避免无效处理。
关于Telnet标识重复的补充处理
如果仍有PuTTy标识重复的问题,是因为Telnet客户端会在连接建立时发送终端协商的控制报文。你可以在添加终止符后增加过滤逻辑(仅保留可打印字符和换行/回车):
// 过滤Telnet控制字符(可选) int valid_idx = 0; for(int i=0; buffer[i]!='\0'; i++){ if(buffer[i] >= 32 || buffer[i] == '\r' || buffer[i] == '\n'){ buffer[valid_idx++] = buffer[i]; } } buffer[valid_idx] = '\0';
内容的提问来源于stack exchange,提问作者unknown
相关产品推荐
相关产品推荐

