c - C TCP write() 和 read() 来自 main 中定义的套接字
问题描述
信息
问题: 我正在尝试从同一个主函数设置 TCP 套接字read()
,write()
但是我不确定如何正确地从套接字读取。
背景信息:我与单独的可执行文件进行通信,一个用于阅读(服务器),另一个用于写作(客户端)。
为此,我使用了这个网站作为指导。https://www.geeksforgeeks.org/tcp-server-client-implementation-in-c/
我从 Remy Lebeau 对C 套接字读取和写入的评论中了解到,返回的套接字accept()
由服务器使用,而返回的套接字socket()
由客户端使用。
我对套接字的写入工作正常。
Awaiting message from a client...
Address: 2, Port: 4547
Socket: 4
Serv addr: -1894572528
Size of server: 16
Message to send to server: hey
sendBytes: 3: hey
Recv bytes: 0
Recieved message:
代码
该程序由三个功能组成
主要的()
createTcpRcvSock()
createTcpSendSock()
函数头及其主体
main(),包含和定义
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <strings.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#define PORT 4547
int main(){
int recvSock,sendSock,recvN,sendN,bufferSize,acceptSock,clilen;
struct sockaddr_in cli_addr;
char sendBuffer[256];
char recvBuffer[256];
recvSock = createTcpRecvSock();
clilen = sizeof(cli_addr);
acceptSock = accept(recvSock, (struct sockaddr *)&cli_addr, clilen);
sendSock = createTcpSendSock();
printf("Message to send to server: ");
bzero(sendBuffer,256);
scanf("%s",&sendBuffer);
bufferSize = strlen(sendBuffer);
sendN = write(sendSock,sendBuffer,bufferSize);
printf("sendBytes: %d: %s\n",sendN,sendBuffer);
if(sendN < 0){
printf("Error writing to socket\n");
}
bzero(recvBuffer,256);
bufferSize = strlen(recvBuffer);
recvN = read(acceptSock,recvBuffer,bufferSize);
printf("Recv bytes: %d\n", recvN);
if(recvN < 0){
printf("Error reading from socket\n");
}
printf("Recieved message: %s\n",recvBuffer);
}
createTcpSendSock()
int createTcpSendSock(){
int sockfd;
struct sockaddr_in serv_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0){
error("ERROR opening socket");
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(PORT);
printf("Socket: %d\n", sockfd);
printf("Serv addr: %d\n", &serv_addr);
printf("Size of server: %d\n", sizeof(serv_addr));
if (connect(sockfd,(struct sockaddr *)&serv_addr ,sizeof(serv_addr)) < 0){
printf("Error connecting: %d: %s\n",errno,strerror(errno));
}
return sockfd;
}
createTcpRecvSock()
int createTcpRecvSock(){
int sockfd,portno,clilen,opt;
struct sockaddr_in serv_addr;
opt = 1;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
error("ERROR opening socket");
}
printf("Success opeing socket\n");
bzero((char *) &serv_addr, sizeof(serv_addr));
if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))){
printf("Setting socket options error: %d: %s\n",errno, strerror(errno));
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(PORT);
printf("Awaiting message from a client...\n");
printf("Address: %d, Port: %d\n", AF_INET, PORT);
if(
bind(sockfd,
(struct sockaddr *) &serv_addr,
sizeof(serv_addr))
< 0)
{
printf("Error on binding: %d, %s\n",errno, strerror(errno));
}
listen(sockfd,6);
return sockfd;
}
预期的
我希望输出Received message: <User entered message>
实际的
但是即使没有循环,程序也会挂起:
Success opeing socket
Awaiting message from a client...
Address: 2, Port: 4547
任何帮助将不胜感激,我已尝试使其尽可能可读。
解决方案
当您以其他方式知道长度时,不要使用字符串函数。它会让你陷入困境。
bzero(recvBuffer,256);
bufferSize = strlen(recvBuffer);
recvN = read(acceptSock,recvBuffer,bufferSize);
您清空缓冲区,使其仅包含零。由于零字节标记字符串的结尾,因此strlen
将返回零。因此,您尝试使用声称大小为零的缓冲区进行读取。
该strlen
功能永远不会告诉您有多少可用空间。它告诉你字符串数据有多大。如果那里没有字符串数据,那么调用strlen
.
然后你这样做:
printf("Recieved message: %s\n",recvBuffer);
虽然它可能适用于您当前的代码方式,但这是一个不好的习惯。返回的read
函数recvN
,您收到的字节数。您忽略了这一点,并要求printf
仅从数据中找出要打印的内容。不要这样做。最终会给你带来麻烦。用于recvN
了解要打印的字节数。
推荐阅读
- sequelize.js - 关联模型的 Sequelize 排序不起作用
- c# - 通过查找表左外连接两个表
- php - 在 WooCommerce 中为特定邮政编码设置最低订购量
- javascript - 如何在 vue 3 中不触发 @update:modelValue 的情况下将 ref 设置为 ajax 调用的值?
- python - Python Boto3 分页错误:“PageIterator”对象不可下标
- javascript - 用于绘图的 React UseEffect
- javascript - Brython:拒绝加载脚本....违反以下内容安全策略指令:“script-src 'self'
- swift - 使用 WebView 以 100% 的比例打开网站
- python - 使用python循环遍历列表以在csv文件中写入新行的问题
- r - 'list' 对象不能被强制输入'integer' -- WRS2 包