我是套接字编程的新手。我试图将服务器连接到多个客户端,我有两个问题。 1)除非我得到回复,否则我无法发送消息,即如果客户端连接并发送消息,则客户端无法再次发送消息,直到它从服务器获得回复。如果客户端键入一些消息,它会存储消息,并在收到消息后发送消息。 2)我想将连接数限制为1,如果某个连接没有其他人应该连接,直到客户端退出客户端。如果客户退出,那么第一个等待的人应该连接。
服务器
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#define MYPORT 3490 /* the port users connect to */
#define BACKLOG 0 /* max no. of pending connections in server queue */
#define MAXDATASIZE 200
void sigchld_handler(int s)
{
while( wait( NULL) > 0); /* wait for any child to finish */
}
int main( void)
{
int listenfd;
/* listening socket */
int connfd;
/* connection socket */
struct sockaddr_in server_addr; /* info for my addr i.e. server */
struct sockaddr_in client_addr; /* client's address info */
int sin_size;
/* size of address structure */
struct sigaction sa; /* deal with signals from dying children! */
int yes = 1;
char clientAddr[ 20]; /* holds ascii dotted quad address */
if ((listenfd = socket( AF_INET, SOCK_STREAM, 0)) == -1)
{
perror( "Server socket");
exit( 1);
}
/* Set Unix socket level to allow address reuse */
if( setsockopt( listenfd, SOL_SOCKET, SO_REUSEADDR,&yes, sizeof( int)) == -1)
{
perror( "Server setsockopt");
exit( 1);
}
sin_size = sizeof( server_addr);
memset( &server_addr, 0, sin_size);
/* zero struct */
server_addr.sin_family = AF_INET;
/* host byte order ... */
server_addr.sin_port = htons( MYPORT); /* . short, network byte order */
server_addr.sin_addr.s_addr = INADDR_ANY; /* any server IP addr */
if( bind( listenfd, (struct sockaddr *)&server_addr,sizeof( struct sockaddr)) == -1)
{
perror( "Server bind");
exit( 1);
}
if( listen( listenfd, BACKLOG) == -1)
{
perror( "Server listen");
exit( 1);
}
/* Signal handler stuff */
sa.sa_handler = sigchld_handler; /* reap all dead processes */
sigemptyset( &sa.sa_mask);
sa.sa_flags = SA_RESTART;
if( sigaction( SIGCHLD, &sa, NULL) == -1)
{
perror( "Server sigaction");
exit( 1);
}
while( 1)
{
/* main accept() loop */
sin_size = sizeof( struct sockaddr_in);
if( (connfd = accept( listenfd,(struct sockaddr *)&client_addr, &sin_size)) == -1)
{
perror( "Server accept");
continue;
}
strcpy( clientAddr, inet_ntoa( client_addr.sin_addr));
printf( "Server: got connection from %s\n", clientAddr);
if( !fork())
{
/* the child process dealing with a client */
char msg[ MAXDATASIZE];
int numbytes;
close( listenfd); /* child does not need the listener */
msg[ 0] = '\0';
/* no message yet! */
do
{
if( (numbytes =recv( connfd, msg, MAXDATASIZE -1, 0)) == -1)
{
perror( "Server recv");
exit( 1);
/* error end of child */
}
msg[ numbytes] = '\0';
/* end of string */
fprintf( stderr, "Message received: %s\n", msg);
do
{
if( strcmp( msg, "quit") == 0)
{
close( connfd);
exit(0);
}
printf( "Message to send: ");
scanf( "%s", msg);
if( send( connfd, msg, strlen( msg), 0) == -1)
{
perror( "server send");
//exit(1);
}
/* error end of child */
}
while( strcmp( msg, "quit") != 0);
if( strcmp( msg, "quit") == 0)
{
close( connfd);
exit(0);
}
//close( connfd);
//exit(0);
/* end of child! */
}
while(1);
//fork();
//close(connfd); /* parent does not need the connection socket */
return 0;
}
}
}
客户端:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
/* for gethostbyname() */
#define PORT 3490
/* server port the client connects to */
#define MAXDATASIZE 100 /* max bytes to be received at once */</i>
int main( int argc, char * argv[])
{
int sockfd, numbytes;
char buf[ MAXDATASIZE];
struct hostent *he;
struct sockaddr_in their_addr; /* server address info */
char msg[ MAXDATASIZE];
if( argc != 2) {
fprintf( stderr, "usage: client hostname\n");
exit( 1);
}
/* resolve server host name or IP address */
if( (he = gethostbyname( argv[ 1])) == NULL) { /* host server info */
perror( "Client gethostbyname");
exit( 1);
}
if( (sockfd = socket( AF_INET, SOCK_STREAM, 0)) == -1) {
perror( "Client socket");
exit( 1);
}
memset( &their_addr, 0, sizeof( their_addr));
/* zero all */
their_addr.sin_family = AF_INET;
/* host byte order .. */
their_addr.sin_port = htons( PORT);
/* .. short, network byte order */
their_addr.sin_addr = *((struct in_addr *)he -> h_addr);
if( connect( sockfd, (struct sockaddr *)&their_addr,
sizeof( struct sockaddr)) == -1) {
perror( "Client connect");
exit( 1);
}
do {
printf( "Message to send: ");
scanf( "%s", msg);
if( (numbytes = send( sockfd, msg, strlen( msg), 0)) == -1) {
perror( "Client send");
continue;
}
if( (numbytes = recv( sockfd, buf, MAXDATASIZE - 1, 0)) == -1) {
perror( "Client recv");
continue;
}
buf[ numbytes] = '\0';
/* end of string char */
printf( "Received: %s\n", buf);
} while( strcmp( msg, "quit") != 0);
close( sockfd);
return 0;
}
答案 0 :(得分:0)
亲爱的,您必须使用多线程来启动新线程来处理新连接
该线程中的也使用单独的线程来接收数据和发送数据......
答案 1 :(得分:0)
1)除非得到回复,否则我无法发送消息,即如果客户端连接 并发送消息,客户端无法再次发送消息,直到它获得 来自服务器的回复。
毫无疑问,因为您已在客户端的scanf
循环中编写了recv
和do
的顺序排列。要按照出现的顺序处理消息输入和套接字接收,我们可以使用select
;您的do
循环可能如下所示:
do
{ fd_set fds;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
FD_SET(sockfd, &fds); // set of descriptors holds stdin and socket
printf("Message to send: "), fflush(stdout);
if (select(sockfd+1, &fds, NULL, NULL, NULL) < 0) break; // error?
// see which descriptors of set are ready
if (FD_ISSET(STDIN_FILENO, &fds))
{ // it is the standard input
scanf("%s", msg);
numbytes = send(sockfd, msg, strlen(msg), 0);
if (numbytes == -1) perror("Client send");
}
if (FD_ISSET(sockfd, &fds))
{ // this is the peer's message or termination
numbytes = recv(sockfd, buf, MAXDATASIZE - 1, 0);
if (numbytes <= 0)
{
perror("Client recv");
break; // no more data from peer, so close the connection
}
buf[numbytes] = '\0'; /* end of string char */
printf("Received: %s\n", buf);
}
} while (strcmp(msg, "quit") != 0);
2)我想将连接数限制为1,如果是的话 连接没有其他人应该连接,直到客户端退出客户端。
我们可以通过不在我们accept
客户端连接请求之后分配服务器进程来实现这一点,而是在唯一的服务器任务本身中处理消息传输(非常相似)如上所示为客户);只需忽略行if( !fork())
以及return 0;
而取消注释close(connfd);
,并在break
时忘记do
循环recv
}返回一个非正值。