我正在尝试在一对客户端和服务器之间建立unix套接字通信,其中客户端和服务器将是在同一台计算机上运行的两个不同进程,并且客户端将从命令行接收输入,并将其传递给服务器,并且服务器将然后用缓冲区响应。两者都应该能够以两种方式随机通信。为此,我在两端打开了套接字,并在无限循环中等待从另一端接收。但是,在客户端,一旦我开始在无限循环中等待recv,就无法向服务器发送命令行指令,则总是在循环中受阻。如果我先向服务器发送命令行指令,则无法从服务器接收任何内容。在服务器上也是如此。我使用select()调用实现了,但是它还在无限循环中等待以获取FD_SET和recv,因此再次陷入了同样的境地。我还尝试过在客户端发送和接收消息时使用不同的线程,但是由于它总是在无限循环中等待,因此我再次陷入了recv中。谁能建议实现这一目标的有效机制。
Code snippet is as below:
#####################################################CLIENT######################################
void* msimcli_RecvFromSocket(void *)
{
int msglength = 0;
int result = 0;
char buffer[CLI_MAX_BUF_SIZE];
pthread_setname_np(pthread_self(), "CliRcThd");
printf("\nWait in Rx on socket descriptor %d\n",datagramSocket.fd);
do{
result = select(datagramSocket.fd + 1, &datagramSocket.rset, NULL, NULL, NULL);
}while(result == -1 && errno == EINTR);
if (result > 0){
if (FD_ISSET(datagramSocket.fd, &datagramSocket.rset))
{
printf("FD SET Rx on socket descriptor %d\n",datagramSocket.fd);
/* The socket_fd has data available to be read */
msglength = recv(datagramSocket.fd, buffer, CLI_MAX_BUF_SIZE, 0);
if (msglength == 0) {
/* This means the other side closed the socket */
close(datagramSocket.fd);
}
else if(msglength > 0){
printf("Message received at cli\n");
printf("Rcvd string = %s\n",(char*)buffer);
/* TBD */
//return 1;
}
}
}
else if (result < 0)
{
/* An error ocurred, just print it to stdout */
printf("Error on select(): %s\n", strerror(errno));
}
}
int msimcli_SendToSocket(void* buf)
{
int rc = ROK;
/*Test buffer*/
cliCmd *buff = (cliCmd *)buf;
printf("Buff %s\n", ((cliCmd *)buf)->buf);
for (int i = 0; i < buff->hdr.msglen; i++)
{
printf("[%x]", buff[i]);
}
printf("\n");
printf("sending on socket [%d]\n",datagramSocket.fd);
rc = sendto(datagramSocket.fd, buf, buff->hdr.msglen, 0, (struct sockaddr *)&datagramSocket.remote, datagramSocket.len);
if (rc == -1) {
printf("%s: errno=0x%x %s\r\n", __FUNCTION__,errno, strerror(errno));
printf("SENDTO ERROR\n"); close(datagramSocket.fd);
return 0;
//exit(1);
}
else {
printf("Data sent!\n");
return rc;
}
}
int msimcli_ConnectToSocket(const char* socketFile,int isSockTypeStreaming,SOCKET_PARAMS* socketParam)
{
int rc = ROK;
int result = 0;
char buffer[CLI_MAX_BUF_SIZE];
int buffer_size = CLI_MAX_BUF_SIZE;
socklen_t len;
MSIM_ZERO(*socketParam);
pthread_t snd_tid;
pthread_t rx_tid;
if (isSockTypeStreaming)
{
socketParam->type = SOCK_STREAM;
}
else
{
socketParam->type = SOCK_DGRAM;
}
socketParam->fd = socket(AF_UNIX, socketParam->type, 0);
if (0 > socketParam->fd)
{
rc = RFAILED;
goto Exit;
}
else
{
printf("socket created successfully with socket descriptor %d\n",socketParam->fd);
}
socketParam->remote.sun_family = AF_UNIX;
strcpy(socketParam->remote.sun_path, socketFile);
socketParam->len = strlen(socketParam->remote.sun_path) + sizeof(socketParam->remote.sun_family) + 1;
FD_ZERO(&socketParam->rset);
FD_SET(socketParam->fd, &socketParam->rset);
/* Create Receiver thread */
if(ROK != (rc = pthread_create(&rx_tid,NULL,msimcli_RecvFromSocket,NULL)))
{
printf("Thread create for Receiver failed\n");
goto Exit;
}
Exit:
if (ROK != rc) {
printf("%s: errno=0x%x %s\r\n", __FUNCTION__,errno, strerror(errno));
if (-1 < socketParam->fd)
{
close(socketParam->fd);
socketParam->fd = -1;
}
}
printf("<< rc %d\r\n", rc);
return rc;
}
int msimcli_ConnectToSocket(const char* socketFile,int isSockTypeStreaming,SOCKET_PARAMS* socketParam)
{
int rc = ROK;
int result = 0;
char buffer[CLI_MAX_BUF_SIZE];
int buffer_size = CLI_MAX_BUF_SIZE;
socklen_t len;
MSIM_ZERO(*socketParam);
pthread_t snd_tid;
pthread_t rx_tid;
if (isSockTypeStreaming)
{
socketParam->type = SOCK_STREAM;
}
else
{
socketParam->type = SOCK_DGRAM;
}
socketParam->fd = socket(AF_UNIX, socketParam->type, 0);
if (0 > socketParam->fd)
{
rc = RFAILED;
goto Exit;
}
else
{
printf("socket created successfully with socket descriptor %d\n",socketParam->fd);
}
socketParam->remote.sun_family = AF_UNIX;
strcpy(socketParam->remote.sun_path, socketFile);
socketParam->len = strlen(socketParam->remote.sun_path) + sizeof(socketParam->remote.sun_family) + 1;
FD_ZERO(&socketParam->rset);
FD_SET(socketParam->fd, &socketParam->rset);
/* Create Receiver thread */
if(ROK != (rc = pthread_create(&rx_tid,NULL,msimcli_RecvFromSocket,NULL)))
{
printf("Thread create for Receiver failed\n");
goto Exit;
}
Exit:
if (ROK != rc){
printf("%s: errno=0x%x %s\r\n", __FUNCTION__,errno, strerror(errno));
if (-1 < socketParam->fd)
{
close(socketParam->fd);
socketParam->fd = -1;
}
}
printf("<< rc %d\r\n", rc);
return rc;
}
##########################################SERVER##########################################
while(1)
{
do{
FD_ZERO(&rset);
FD_SET(serverDatagramSocket, &rset);
result = select(serverDatagramSocket + 1, &rset, NULL, NULL, NULL);
} while (result == -1 && errno == EINTR);
if (result > 0) {
if (FD_ISSET(serverDatagramSocket, &rset)) {
/* The socket_fd has data available to be read */
msgLength = recv(serverDatagramSocket,buffer,CLI_MAX_BUF_SIZE, 0);
if (msgLength == 0) {
printf("MsgLength zero, other side closed the socket\n");
/* This means the other side closed the socket */
close(serverDatagramSocket);
}
else if (msgLength > 0){
printf("MsgLength nonzero, message received on socket[%d]\n",serverDatagramSocket);
recvdCli.hdr.msglen = ((cliCmd *)buffer)->hdr.msglen;
recvdCli.hdr.msgtype = ((cliCmd *)buffer)->hdr.msgtype;
uint16_t buff_len = (recvdCli.hdr.msglen - sizeof(recvdCli.hdr));
strncpy((char *)recvdCli.buf, (char *)((cliCmd *)buffer)->buf, buff_len);
recvdCli.buf[buff_len] = '\0';
printf("hdr length : %d\n", recvdCli.hdr.msglen);
printf("hdr msgtype : %d\n", recvdCli.hdr.msgtype);
printf("buffer length : %d\n", buff_len);
printf("buffer : %s\n", recvdCli.buf);
/* Test send */
//FD_CLR(serverDatagramSocket,&rset);
macsim_SendDatagram((void*)str);
//return 1;
}
}
}
else if (result < 0) {
/* An error ocurred, just print it to stdout */
printf("Error on select():%s\n",strerror(errno));
else if (result < 0) {
/* An error ocurred, just print it to stdout */
printf("Error on select(): %s\n", strerror(errno));
}
Exit:
if (NULL != buffer)
{
free(buffer);
}
if (-1 != serverDatagramSocket)
{
close(serverDatagramSocket);
serverDatagramSocket = 1;
}
printf("<<rc = %d\r\n", rc);
return rc;
}
int macsim_SendDatagram(void *buffer)
{
int rc = ROK;
/*Test buffer*/
printf("MACSIM Test Buffer is %s\n", (char*)buffer);
printf("\n");
printf("Trying to send on socket descripor [%d]\n",macsimDatagramSocket.fd);
rc = sendto(macsimDatagramSocket.fd, buffer, strlen((char*)buffer), 0, \
(struct sockaddr *)&macsimDatagramSocket.remote, macsimDatagramSocket.len);
if (rc == -1) {
printf("%s: errno=0x%x %s\r\n", __FUNCTION__,errno, strerror(errno));
printf("SENDTO ERROR\n");
close(macsimDatagramSocket.fd);
return 0;
}
else {
printf("Data sent!\n");
return rc;
}
}
**Ouputs as follow:**
***Output at server:***
--------------------------------------------------------------
/*************************************************/
Open server socket
>>
>> socketFile=/dev/shm/sockets/logClient
Got opened with sock[6]
<< sock 6
Serever socket created with fd = 6
--------------------------------------------------
MsgLength nonzero, message received on socket[6]
hdr length : 13
hdr msgtype : 0
buffer length : 5
buffer : test1
MACSIM Test Buffer is TC Rcvd
Trying to send on socket descripor [6]
macsim_SendDatagram: errno=0x6b Transport endpoint is not connected
SENDTO ERROR
***Output at client:***
root@adkumar:/home/adkumar/git/5G_DU/src/macsim/bin# ./cli
Start cli
socket created successfully with socket descriptor 3
<< rc 0
*********************************
MENU
***********************************
1)runtest()
1)stoptest()
2)rerunlasttest()
0)exit()
Enter option from above menu:
Wait in Rx on socket descriptor 3
1
Enter TC to run
test1
Buff : test1
sending on socket [3]
Data sent!
*********************************
MENU
***********************************
1)runtest()
1)stoptest()
2)rerunlasttest()
0)exit()
Enter option from above menu:1
Enter TC to run
test2
Buff : test2
sending on socket [3]
msimcli_SendToSocket: errno=0x6f Connection refused
SENDTO ERROR