用accept接收顺序数据
我正在尝试在两个站点(a和B)之间建立通信。A应该向B发送多个数据(反之亦然):“多个数据”意味着我希望在一个接受会话中使用来自两个站点的send和recv。目前,我只是试图在每个连接上发送超过1个数据包。因为我不熟悉处理套接字,所以很可能我还没有完全理解套接字背后的概念。在下面的代码中,接收机成功地检索到发射机发送的第一个int,但没有检索到下面的int。你能告诉我我做错了什么吗用accept接收顺序数据,c,sockets,networking,C,Sockets,Networking,我正在尝试在两个站点(a和B)之间建立通信。A应该向B发送多个数据(反之亦然):“多个数据”意味着我希望在一个接受会话中使用来自两个站点的send和recv。目前,我只是试图在每个连接上发送超过1个数据包。因为我不熟悉处理套接字,所以很可能我还没有完全理解套接字背后的概念。在下面的代码中,接收机成功地检索到发射机发送的第一个int,但没有检索到下面的int。你能告诉我我做错了什么吗 #include <stdio.h> #include <stdlib.h> #inclu
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <errno.h>
#define DATA_TO_SEND_LENGTH 9
#define PRINT_ERRNO_EXIT(who,id) { \
int verrno=errno; \
printf("%s ERRNO: %d\nexit id: %d\n",who==0?"sender":"receiver",verrno,id); \
return id; \
}
int main(){
char* ipaddress="127.0.0.1";
int portNumber=12345;
int socketOptionalValue=1;
const int dataToSend[]={1,2,3,4,5,6,7,8,9};
if (fork()==0){
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// @@@@@@@@@@@@@@@ CHILD: HE IS THE SENDER @@@@@@@@@@@@@@@@
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
int socketSenderDescriptor;
struct sockaddr_in destinationInfos;
struct sockaddr_in tmp;
int i;
// ************** CREATE AND OPEN THE SOCKET *****************
inet_aton(ipaddress,&tmp.sin_addr);
socketSenderDescriptor = socket(AF_INET, SOCK_STREAM, 0); // socket file descriptor
if (socketSenderDescriptor < 0 ){
PRINT_ERRNO_EXIT(0,1);
}
if (setsockopt(socketSenderDescriptor,SOL_SOCKET,SO_REUSEADDR,&socketOptionalValue,sizeof(socketOptionalValue))!=0){
PRINT_ERRNO_EXIT(0,2);
}
if (setsockopt(socketSenderDescriptor,SOL_SOCKET,SO_KEEPALIVE,&socketOptionalValue,sizeof(socketOptionalValue))!=0){
PRINT_ERRNO_EXIT(0,2);
}
memset(&destinationInfos,0,sizeof(destinationInfos)); //clean the structure used to store destination information
destinationInfos.sin_family=AF_INET; //we want to use inet class
destinationInfos.sin_addr.s_addr=tmp.sin_addr.s_addr;//Set destination IP
destinationInfos.sin_port=htons(portNumber); //communiction port number
//connection
if (connect(socketSenderDescriptor,(struct sockaddr *)&(destinationInfos),sizeof(destinationInfos)) < 0){
PRINT_ERRNO_EXIT(0,3);
}
// ******************* SEND DATA **********************
sleep(1); //wait for the parent to start listening...
for (i=0;i<DATA_TO_SEND_LENGTH;i++){
printf("sender: i'm sending %d\n",dataToSend[i]);
send(socketSenderDescriptor,&(dataToSend[i]),sizeof(dataToSend[i]),0);
sleep(1);
}
// ******************* CLOSE SOCKET *******************
if (close(socketSenderDescriptor)!=0){
PRINT_ERRNO_EXIT(0,4);
}
printf("SENDER FINISH!\n");
return EXIT_SUCCESS;
}else {
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// @@@@@@@@@@@@@@@@ PARENT: HE IS THE RECEIVER @@@@@@@@@@@@
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
struct sockaddr_in remoteSocketInfos;
struct sockaddr_in localSocketInfos;
int localSocketDescriptor;
int sessionSocket;
int valueReceived;
int i=0;
static socklen_t socksize=sizeof(struct sockaddr_in);
// ******************* CREATE AND BIND THE SOCKET ******************
//write inside localSocketInfos the information about our server
memset(&localSocketInfos,0,sizeof(localSocketInfos));
localSocketInfos.sin_family=AF_INET;
localSocketInfos.sin_addr.s_addr=htonl(INADDR_ANY);
localSocketInfos.sin_port= htons(portNumber);
//create the main socket where all connection to our server will be received
localSocketDescriptor=socket(AF_INET,SOCK_STREAM,0);
if (localSocketDescriptor<0){
PRINT_ERRNO_EXIT(1,1);
}
//On Linux, SO_REUSEADDR allows you to bind to an address unless an active connection is present
//see https://stackoverflow.com/questions/4979425/difference-between-address-in-use-with-bind-in-windows-and-on-linux-errno
setsockopt(localSocketDescriptor,SOL_SOCKET,SO_REUSEADDR,&socketOptionalValue,sizeof(socketOptionalValue));
//Bind our socket to the socketDescription: this allows the machine to know the data
//received on the port specified in the sockaddr_in should be handled by our specified socket.
if (bind(localSocketDescriptor,(struct sockaddr*)&localSocketInfos,sizeof(struct sockaddr))!=0){
PRINT_ERRNO_EXIT(1,2);
}
//tells our program to start listening the socket we have created. This will NOT block the flow of the program because
//we are not waiting anything at all.
if (listen(localSocketDescriptor,10)!=0){
PRINT_ERRNO_EXIT(1,3);
}
// ************************ WAIT FOR CONNECTIONS ********************
do {
i++;
printf("Waiting transmission on %s, port %d...\n",inet_ntoa(localSocketInfos.sin_addr),localSocketInfos.sin_port);
sessionSocket=accept(localSocketDescriptor,(struct sockaddr*)&remoteSocketInfos,&socksize);
if (sessionSocket<0){
int verrno=errno;
printf("receiver ERRNO: %d\n",verrno);
continue;
}
printf("Incoming transmission from %s, port %d...\n",inet_ntoa(remoteSocketInfos.sin_addr),remoteSocketInfos.sin_port);
recv(sessionSocket,&valueReceived,sizeof(valueReceived),0);
printf("DATA READ! %d\n",valueReceived);
close(sessionSocket);
} while(i<DATA_TO_SEND_LENGTH);
if (close(localSocketDescriptor)==0){
PRINT_ERRNO_EXIT(1,4);
}
printf("RECEIVER FINISH!\n");
return EXIT_SUCCESS;
}
}
在接收方进程中,
accept()
只需要调用一次。由于将accept()
放入while
循环中,循环的第二次迭代将在accept
上被阻止,因为没有新连接进入
一个简单的解决方法是将accept
从循环中排除。您可以尝试以下修复,看看它是否有效。请注意,关闭
也会在循环后移动
// ************************ WAIT FOR CONNECTIONS ********************
printf("Waiting transmission on %s, port %d...\n",inet_ntoa(localSocketInfos.sin_addr),localSocketInfos.sin_port);
sessionSocket=accept(localSocketDescriptor,(struct sockaddr*)&remoteSocketInfos,&socksize);
if (sessionSocket<0){
int verrno=errno;
printf("receiver ERRNO: %d\n",verrno);
PRINT_ERRNO_EXIT(1,5);
}
do {
i++;
printf("Incoming transmission from %s, port %d...\n",inet_ntoa(remoteSocketInfos.sin_addr),remoteSocketInfos.sin_port);
recv(sessionSocket,&valueReceived,sizeof(valueReceived),0);
printf("DATA READ! %d\n",valueReceived);
} while(i<DATA_TO_SEND_LENGTH);
close(sessionSocket);
/*******************等待连接********************
printf(“在%s上等待传输,端口%d...n”,inet_ntoa(localsocketingfos.sin_addr),localsocketingfos.sin_端口);
sessionSocket=accept(localSocketDescriptor,(struct sockaddr*)和remotesocketinfo,&socksize);
如果(sessionSocketI按照您的建议进行了尝试,但接收器以这种方式从套接字读取随机数据:两个电台不同步。为了避免这种情况,我真的必须在通信中手动执行同步序列吗?我不确定如何继续。@Koldar它们应该同步。我自己尝试过,但没有看到任何同步问题。希望您已经找到正确的解决方法。
// ************************ WAIT FOR CONNECTIONS ********************
printf("Waiting transmission on %s, port %d...\n",inet_ntoa(localSocketInfos.sin_addr),localSocketInfos.sin_port);
sessionSocket=accept(localSocketDescriptor,(struct sockaddr*)&remoteSocketInfos,&socksize);
if (sessionSocket<0){
int verrno=errno;
printf("receiver ERRNO: %d\n",verrno);
PRINT_ERRNO_EXIT(1,5);
}
do {
i++;
printf("Incoming transmission from %s, port %d...\n",inet_ntoa(remoteSocketInfos.sin_addr),remoteSocketInfos.sin_port);
recv(sessionSocket,&valueReceived,sizeof(valueReceived),0);
printf("DATA READ! %d\n",valueReceived);
} while(i<DATA_TO_SEND_LENGTH);
close(sessionSocket);