我有以下客户端和服务器代码。
server.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/utsname.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<netdb.h>
#include<unistd.h>
#define MAX_DATA 1024
#define BUFFER 1024
int _GetHostName(char *buffer, int lenght);
const char MESSAGE[]="Hello, World!\n";
const int BACK_LOG=5;
int main(int argc, char *argv[]){
int serverSocket=0, on=0, port=0, status=0, childPid=0;
struct hostent *hostPtr=NULL;
char hostname[80]="";
char data[MAX_DATA];
struct sockaddr_in serverName={0};
char input[BUFFER];
char output[BUFFER];
int len;
if(2!= argc){
fprintf(stderr, "Usage : %s <port>\n", argv[0]);
exit(1);
}
port=atoi(argv[1]);
serverSocket=socket(PF_INET,SOCK_STREAM, IPPROTO_TCP);
if(-1==serverSocket){
perror("socket()");
exit(1);
}
on=1;
status=setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
if(-1==status){
perror("setsockopt(...,SO_REUSEADDRE,...)");
}
{
struct linger linger={0};
linger.l_onoff=1;
linger.l_linger=30;
status=setsockopt(serverSocket, SOL_SOCKET, SO_LINGER, (const char*)&linger, sizeof(linger));
if(-1==status){
perror("setsockopt(...,SO_LINGER,...)");
}
}
status=_GetHostName(hostname, sizeof(hostname));
if(-1==status){
perror("_GetHostName()");
exit(1);
}
hostPtr=gethostbyname(hostname);
if(NULL==hostPtr){
perror("gethostbyname()");
exit(1);
}
(void)memset(&serverName,0,sizeof(serverName));
(void)memcpy(&serverName.sin_addr, hostPtr->h_addr,hostPtr->h_length);
serverName.sin_family=AF_INET;
serverName.sin_port=htons(port);
status=bind(serverSocket, (struct sockaddr*)&serverName,sizeof(serverName));
if(-1==status){
perror("bind");
exit(1);
}
status=listen(serverSocket, BACK_LOG);
if(-1==status){
perror("listen()");
exit(1);
}
for(;;){
struct sockaddr_in clientName={0};
int slaveSocket, clientLength=sizeof(clientName);
(void)memset(&clientName,0,sizeof(clientName));
slaveSocket=accept(serverSocket,(struct sockaddr*)&clientName, & clientLength);
if(-1==slaveSocket){
perror("accept()");
exit(1);
}
childPid=fork();
switch(childPid){
case -1:perror("fork()");
exit(1);
case 0: close(serverSocket);
if(-1==getpeername(slaveSocket, (struct sockaddr*)&clientName, &clientLength)){
perror("getpeername()");
}else{
printf("Connection request from %s \n", inet_ntoa(clientName.sin_addr));
int data_len=1;
while(data_len){
data_len=recv(slaveSocket,data, MAX_DATA,0);
if(data_len){
//send(slaveSocket,data,data_len,0);
data[data_len]='\0';
printf("CLIENT: %s", data);
printf("SERVER : ");
fgets(input,BUFFER, stdin);
send(slaveSocket, input, strlen(input),0);
}
}
}
printf("Client disconnected\n");
close(slaveSocket);
exit(0);
default:close(slaveSocket);
}
}
return 0;
}
int _GetHostName(char *buffer,int length){
struct utsname sysname={0};
int status=0;
status=uname(&sysname);
if(-1!=status){
strncpy(buffer,sysname.nodename,length);
}
return(status);
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#define BUFFER 1024
int main(int argc, char *argv[]){
int clientSocket, remotePort, status=0;
struct hostent *hostPtr=NULL;
struct sockaddr_in serverName={0};
char buffer[256]="";
char *remoteHost=NULL;
char input[BUFFER];
char output[BUFFER];
int len;
if(3!=argc){
fprintf(stderr, "Usage: %s <serverHost> <serverPort> \n",argv[0]);
exit(1);
}
remoteHost=argv[1];
remotePort=atoi(argv[2]);
clientSocket=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
if(-1==clientSocket){
perror("socket()");
exit(1);
}
hostPtr=gethostbyname(remoteHost);
if(NULL==hostPtr){
hostPtr=gethostbyaddr(remoteHost,strlen(remoteHost), AF_INET);
if(NULL==hostPtr){
perror("Error resolving server address ");
exit(1);
}
}
serverName.sin_family=AF_INET;
serverName.sin_port=htons(remotePort);
(void)memcpy(&serverName.sin_addr,hostPtr->h_addr,hostPtr->h_length);
status=connect(clientSocket,(struct sockaddr*)&serverName,sizeof(serverName));
if(-1==status){
perror("connect()");
exit(1);
}
while(1){
printf("CLIENT: ");
fgets(input,BUFFER, stdin);
send(clientSocket, input, strlen(input),0);
len=recv(clientSocket, output,BUFFER, 0);
output[len]='\0';
printf("SERVER : %s\n",output);
}
close(clientSocket);
}
上面的服务器代码可以从客户端接收和发送消息。客户端还可以从服务器接收消息并向服务器发送消息。但是,他们一次只能发送一条消息。在客户端可以发送更多消息之前,需要先等待服务器发送单个消息。与服务器相同。 如何让他们接收和发送多条消息而无需等待另一方回复?
答案 0 :(得分:1)
我的理解是,您希望继续发送而无需等待服务器的响应。
实现它的一种简单方法是使用poll()
函数首先检查任何响应。只有当您确定要读取数据时,才会致电recv()
。
int pollForData(int sock) {
struct pollfd pollSock;
pollSock.fd = sock;
pollSock.events = POLLIN;
return poll(&pollSock, 1, 10);
}
答案 1 :(得分:1)
在套接字和stdin
上使用select()
,并从两者中的任何一个进行读取/接收。如果读取完成,则写入/发送到stdout
或插座。
在服务器“套接字”中将引用接受套接字,在客户端中引用已连接的套接字。
无关,但仍然很重要:
此
char data[MAX_DATA];
...
data_len=recv(slaveSocket,data, MAX_DATA,0);
if(data_len){
data[data_len]='\0';
...
可能会在收到MAX_DATA
个字节时导致缓冲区溢出,因此0
将在data
的末尾写入1。
要修复此定义data
,请执行以下操作:
char data[MAX_DATA + 1];
所有代码完全错过了对recv()
和send()
的调用的错误检查。这很糟糕。