簡體   English   中英

套接字,使用SOCK_DGRAM的客戶端服務器通信,epoll

[英]Sockets, client server communication using SOCK_DGRAM, epoll

我正在嘗試使用AF_INET,SOCK_DGRAM編寫程序,客戶端連接到服務器時會向其發送消息"First message" ,然后服務器會使用"Second message"來響應客戶端。

Q1:我的代碼服務器中收到"First message" ,但是客戶端沒有得到服務器響應"Second message" ,為什么?

Q2:在客戶端中,我使用msg_addr.sin_addr.s_addr =INADDR_ANY;連接到服務器msg_addr.sin_addr.s_addr =INADDR_ANY; 我想將其更改為: msg_addr.sin_addr.s_addr =htonl(inet_addr("172.126.154.12")); 其中ip "172.126.154.12"是服務器ip;

server.c

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>        
#include <sys/socket.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <errno.h>
#include <signal.h>
 #include <string.h>


typedef struct{
    int type;
    int arg1;
    int arg2;
    int result;
    char name[50];
}Msg;

#define WRITE(format, ...) { char buffer[255]; sprintf(buffer, format, ##__VA_ARGS__); write(1, buffer, strlen(buffer));}
#define FAILURE_EXIT(format, ...) { char buffer[255]; sprintf(buffer, format, ##__VA_ARGS__); write(1, buffer, strlen(buffer));exit(-1);}


int web_fd, epoll;
struct sockaddr_in server_addr;
Msg msg;
struct sockaddr msg_addr;


int main(int argc, char *argv[]){


    if((web_fd = socket(AF_INET, SOCK_DGRAM,0)) == -1) FAILURE_EXIT("Failed to create communication endpoint web_fd\n");
    int yes=1;
    if (setsockopt(web_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) == -1) FAILURE_EXIT("setsockopt web_fd\n");


    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(9992);
    server_addr.sin_addr.s_addr = INADDR_ANY;

    if(bind(web_fd,(const struct sockaddr*) &server_addr,sizeof(struct sockaddr)) == -1) FAILURE_EXIT("Failed to assign server_addr to a web_fd: %s\n",strerror(errno));

    epoll = epoll_create1(0);
    if(epoll == -1) FAILURE_EXIT("Failed to create new epoll instance: %s\n",strerror(errno));
    struct epoll_event event;
    event.events = EPOLLIN;
    event.data.fd = web_fd;
    if(epoll_ctl(epoll,EPOLL_CTL_ADD,web_fd,&event)== -1) FAILURE_EXIT("Failed to register web_fd file descriptor on epoll instance:   %s\n",strerror(errno));

    printf("Server starts loop.\n");

    while(1){

        struct epoll_event event;
        WRITE("Waiting for client message...\n");
        int nfd = epoll_wait(epoll,&event,1,-1);

        if(event.data.fd == web_fd){

            recvfrom(event.data.fd,&msg,sizeof(Msg),0 ,&msg_addr,0);
            WRITE("Received message from client %s\n",msg.name);
            strcpy(msg.name,"Second message");
            sendto(event.data.fd,&msg,sizeof(Msg),0 ,(struct sockaddr*)&msg_addr, (socklen_t) sizeof(msg_addr) );


        }else{
            WRITE("Unknown descriptor\n");
        }
    }
}

client.c

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>        
#include <sys/socket.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <errno.h>
#include <signal.h>
#include <string.h>

typedef struct{
    int type;
    int arg1;
    int arg2;
    int result;
    char name[50];
}Msg;

#define WRITE(format, ...) { char buffer[255]; sprintf(buffer, format, ##__VA_ARGS__); write(1, buffer, strlen(buffer));}
#define FAILURE_EXIT(format, ...) { char buffer[255]; sprintf(buffer, format, ##__VA_ARGS__); write(1, buffer, strlen(buffer));exit(-1);}


int socket_fd;
struct sockaddr_in msg_addr;
Msg msg;


int main(int argc, char *argv[]){

    struct sockaddr_in msg_addr;
    msg_addr.sin_family = AF_INET;    
    msg_addr.sin_addr.s_addr =INADDR_ANY;
    msg_addr.sin_port = htons(9992);

    socket_fd = socket(AF_INET, SOCK_DGRAM,0);
    if(socket_fd == -1) FAILURE_EXIT("Failed to create client socket\n");

    if(connect(socket_fd, (const struct sockaddr*) &msg_addr, sizeof(struct sockaddr)) == -1) FAILURE_EXIT("Failed to assign server_addr to a web_fd: %s\n",strerror(errno));

    strcpy(msg.name,"First message ");   
    sendto(socket_fd,&msg,sizeof(Msg),0 ,(struct sockaddr*)&msg_addr,(socklen_t) sizeof(Msg));

   WRITE("Waiting..\n");
    recvfrom(socket_fd,&msg,sizeof(Msg),0 ,0,0);    
    WRITE("f %s\n",msg.name);


    WRITE("I registered\n");

    sleep(400);


}

在服務器代碼中更改recvfrom()調用如下

socklen_t addrsize;
recvfrom(event.data.fd,&msg,sizeof(Msg),0 ,&msg_addr, &addrsize);

並以此更改后續的sendto()調用

sendto(event.data.fd,&msg,sizeof(Msg),0 ,(struct sockaddr*)&msg_addr, addrsize);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM