📄 chatmb.c
字号:
#include <sys/utsname.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <error.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
//#define struct sockaddr ( struct sockaddr )
#define MAXLINE 4096
void recv_all ( int , socklen_t );
void send_all ( int sendfd , struct sockaddr * sadest ,socklen_t salen , const char * name );
int udp_client(const char *host, const char *serv, struct sockaddr **saptr, socklen_t *lenp);
char *sock_ntop(const struct sockaddr *sa, socklen_t salen);
int main ( int argc , char ** argv )
{
int sendfd ;
int recvfd ;
socklen_t templen;
socklen_t salen ;
const int on = 1 ;
const int flag = 0 ;
struct sockaddr *sasend ;
struct sockaddr *sarecv ;
struct ip_mreq req;
struct sockaddr_in tempaddr ;
if ( argc != 4 ) {
printf ( "Usage : chat < IP-multicast-address > < port > < name >\n" );
exit ( 0 );
}
printf ( "\nThe program is for chat !\n\n" );
sendfd = udp_client ( argv [1] , argv [2] , ( struct sockaddr ** )&sasend , &salen );
recvfd = socket ( sasend -> sa_family , SOCK_DGRAM , 0 );
setsockopt ( recvfd , SOL_SOCKET , SO_REUSEADDR , & on , sizeof ( on ) );
sarecv = malloc ( salen ) ;
memcpy ( sarecv , sasend , salen );
bind ( recvfd , sarecv ,salen );
memcpy(&req.imr_multiaddr , & ( ( const struct sockaddr_in * )sasend ) -> sin_addr , sizeof ( struct in_addr ) );
req.imr_interface.s_addr = htonl ( INADDR_ANY );
setsockopt ( recvfd , IPPROTO_IP , IP_ADD_MEMBERSHIP , &req , sizeof ( req ) );
setsockopt ( recvfd , IPPROTO_IP , IP_MULTICAST_LOOP , &flag , sizeof ( flag ) );
if ( fork ( ) == 0 )
recv_all ( recvfd , salen );
send_all ( sendfd , sasend , salen ,argv[3] ) ;
}
void send_all ( int sendfd , struct sockaddr * sadest ,socklen_t salen ,const char * name )
{
static char line[MAXLINE];
static char chat[MAXLINE + 1];
static char say [ ] = "say :";
struct utsname myname;
int n;
if ( uname ( &myname ) < 0 ) {
perror ( "uname error" ) ;
exit ( 1 ) ;
}
snprintf( line ,sizeof ( line ) , "%s, %d\n%s %s " , myname.nodename , getpid () , name , say );
n = strlen ( line ) ;
while ( fgets ( chat , MAXLINE , stdin ) != NULL ){
strcat( line , chat );
sendto ( sendfd , line , strlen ( line ) , 0 , sadest , salen ) ;
strncpy( line , line , n );
line [n] = '\0';
}
}
void recv_all ( int recvfd , socklen_t salen )
{
int n ;
char line[MAXLINE + 1] ;
socklen_t len ;
struct sockaddr * safrom ;
safrom = malloc ( salen ) ;
for ( ; ; ) {
len = salen ;
n = recvfrom ( recvfd , line , MAXLINE , 0 , safrom , & len ) ;
line [ n ] = 0 ;
printf ( "\n\033[01;34mfrom %s : %s" , sock_ntop ( safrom ,len ) , line ) ;
printf ( "\033[0m\n" );
}
}
int udp_client(const char *host, const char *serv, struct sockaddr **saptr, socklen_t *lenp)
{
int sockfd, n;
struct addrinfo hints, *res, *ressave;
bzero(&hints, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0){
printf ("udp_client error for %s, %s: %s",
host, serv, gai_strerror(n));
exit ( 1 ) ;
}
ressave = res;
do {
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sockfd >= 0)
break; /* success */
} while ( (res = res->ai_next) != NULL);
if (res == NULL) /* errno set from final socket() */
printf("udp_client error for %s, %s", host, serv);
*saptr = malloc(res->ai_addrlen);
memcpy(*saptr, res->ai_addr, res->ai_addrlen);
*lenp = res->ai_addrlen;
freeaddrinfo(ressave);
return(sockfd);
}
char *sock_ntop(const struct sockaddr *sa, socklen_t salen)
{
char portstr[8];
static char str[128]; /* Unix domain is largest */
switch (sa->sa_family) {
case AF_INET: {
struct sockaddr_in *sin = (struct sockaddr_in *) sa;
if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL)
return(NULL);
if (ntohs(sin->sin_port) != 0) {
snprintf(portstr, sizeof(portstr), ":%d", ntohs(sin->sin_port));
strcat(str, portstr);
}
return(str);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -