linux c socket recv,linux c socket之通用socket,支持ipv4和ipv6

/*

* File: TCPEchoClient.c

* Author: 云守护 通用客户端

*

* Created on 2013年11月13日, 下午3:49

*/

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include "DieWithMessage.h"

//建立客户端socket

int SetupTCPClientSocket(const char *host,const char* service)

{

//配置想要的地址信息

struct addrinfo addrCriteria;

memset(&addrCriteria,0,sizeof(addrCriteria));

addrCriteria.ai_family=AF_UNSPEC;

addrCriteria.ai_socktype=SOCK_STREAM;

addrCriteria.ai_protocol=IPPROTO_TCP;

struct addrinfo *server_addr;

//获取地址信息

int retVal=getaddrinfo(host,service,&addrCriteria,&server_addr);

if(retVal!=0)

DieWithUserMessage("getaddrinfo() failed!",gai_strerror(retVal));

int sock=-1;

struct addrinfo *addr=server_addr;

while(addr!=NULL)

{

//建立socket

sock=socket(addr->ai_family,addr->ai_socktype,addr->ai_protocol);

if(sock<0)

continue;

if(connect(sock,addr->ai_addr,addr->ai_addrlen)==0)

{

//链接成功,就中断循环

break;

}

//没有链接成功,就继续尝试下一个

close(sock);

sock=-1;

addr=addr->ai_next;

}

freeaddrinfo(server_addr);

return sock;

}

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

if(argc<3||argc>4)

{

DieWithUserMessage("param"," []");

}

char *server=argv[1];

char* echoString=argv[2];

char * service=(argc==4)?argv[3]:"echo";

//建立链接

int sock=SetupTCPClientSocket(server,service);

if(sock<0)

DieWithUserMessage("SetupTCPClientSocket failed!","Unable to connect");

size_t echoStringLen=strlen(echoString);

//发送数据

ssize_t numBytes=send(sock,echoString,echoStringLen,0);

if(numBytes<0)

DieWithSystemMessage("send() failed!");

else if(numBytes!=echoStringLen)

{

DieWithUserMessage("send() ","sent unexpected number of bytes");

}

unsigned int totalBytesRcvd=0;

fputs("Received:",stdout);

while(totalBytesRcvd

{

char buffer[BUFSIZ];

//接收数据

numBytes=recv(sock,buffer,BUFSIZ-1,0);

if(numBytes<0)

DieWithSystemMessage("recv() failed!");

else if(numBytes==0)

{

DieWithUserMessage("recv()","connection closed prematurely");

}

totalBytesRcvd+=numBytes;

buffer[numBytes]='\0';

//打印到控制台

fputs(buffer,stdout);

}

fputc('\n',stdout);

close(sock);

return (EXIT_SUCCESS);

}

/*

* File: TCPEchoServer.c 通用服务端

* Author: 云守护

* Created on 2013年11月14日, 上午10:10

*/

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include "DieWithMessage.h"

void PrintSocketAddress(const struct sockaddr *address, FILE *stream) {

// Test for address and stream

if (address == NULL || stream == NULL)

return;

void *numericAddress; // Pointer to binary address

// Buffer to contain result (IPv6 sufficient to hold IPv4)

char addrBuffer[INET6_ADDRSTRLEN];

in_port_t port; // Port to print

// Set pointer to address based on address family

switch (address->sa_family) {

case AF_INET:

numericAddress = &((struct sockaddr_in *) address)->sin_addr;

port = ntohs(((struct sockaddr_in *) address)->sin_port);

break;

case AF_INET6:

numericAddress = &((struct sockaddr_in6 *) address)->sin6_addr;

port = ntohs(((struct sockaddr_in6 *) address)->sin6_port);

break;

default:

fputs("[unknown type]", stream); // Unhandled type

return;

}

// Convert binary to printable address

if (inet_ntop(address->sa_family, numericAddress, addrBuffer,

sizeof(addrBuffer)) == NULL)

fputs("[invalid address]", stream); // Unable to convert

else {

fprintf(stream, "%s", addrBuffer);

if (port != 0) // Zero not valid in any socket addr

fprintf(stream, "-%u", port);

}

}

static const int MAXPENDING=5;

int SetupTCPServerSocket(const char *service)

{

//配置地址信息

struct addrinfo addrCriteria;

memset(&addrCriteria,0,sizeof(addrCriteria));

addrCriteria.ai_family=AF_UNSPEC;

addrCriteria.ai_flags=AI_PASSIVE;

addrCriteria.ai_socktype=SOCK_STREAM;

addrCriteria.ai_protocol=IPPROTO_TCP;

struct addrinfo *server_addr;

//获取地址信息

int retVal=getaddrinfo(NULL,service ,&addrCriteria,&server_addr);

if(retVal!=0)

DieWithUserMessage("getaddrinfo failed!",gai_strerror(retVal));

int server_sock=-1;

struct addrinfo *addr=server_addr;

while(addr!=NULL)

{

//建立socket

server_sock=socket(server_addr->ai_family,server_addr->ai_socktype,server_addr->ai_protocol);

if(server_sock<0)

continue;

//绑定端口和监听端口

if((bind(server_sock,server_addr->ai_addr,server_addr->ai_addrlen)==0)&& listen(server_sock,MAXPENDING)==0)

{

struct sockaddr_storage local_addr;

socklen_t addr_size=sizeof(local_addr);

if(getsockname(server_sock,(struct sockaddr *)&local_addr,&addr_size)<0)

{

DieWithSystemMessage("getsockname() failed!");

}

fputs("Binding to ",stdout);

PrintSocketAddress((struct sockaddr*)&local_addr,stdout);

fputc('\n',stdout);

break;

}

close(server_sock);

server_sock=-1;

addr=addr->ai_next;

}

freeaddrinfo(server_addr);

return server_sock;

}

void HandleTCPClient(int clntSocket) {

char buffer[BUFSIZ]; // Buffer for echo string

// Receive message from client

ssize_t numBytesRcvd = recv(clntSocket, buffer, BUFSIZ, 0);

if (numBytesRcvd < 0)

DieWithSystemMessage("recv() failed");

// Send received string and receive again until end of stream

while (numBytesRcvd > 0) { // 0 indicates end of stream

// Echo message back to client

ssize_t numBytesSent = send(clntSocket, buffer, numBytesRcvd, 0);

if (numBytesSent < 0)

DieWithSystemMessage("send() failed");

else if (numBytesSent != numBytesRcvd)

DieWithUserMessage("send()", "sent unexpected number of bytes");

// See if there is more data to receive

numBytesRcvd = recv(clntSocket, buffer, BUFSIZ, 0);

if (numBytesRcvd < 0)

DieWithSystemMessage("recv() failed");

}

close(clntSocket); // Close client socket

}

int acceptTCPConnection(int server_sock)

{

struct sockaddr_storage client_addr;

socklen_t client_addrLen=sizeof(client_addr);

int client_sock=accept(server_sock,(struct sockaddr *)&client_addr,&client_addrLen);

if(client_sock<0)

DieWithSystemMessage("accept() failed!");

fputs("Handing client ",stdout);

PrintSocketAddress((struct sockaddr*)&client_addr,stdout);

fputc('\n',stdout);

return client_sock;

}

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

if(argc!=2)

DieWithUserMessage("param","");

char * service=argv[1];

int server_sock=SetupTCPServerSocket(service);

if(server_sock<0)

{

DieWithUserMessage("SetupTCPServerSocket() failed!",service);

}

for(;;)

{

int client_sock=acceptTCPConnection(server_sock);

HandleTCPClient(client_sock);

close(client_sock);

}

return (EXIT_SUCCESS);

}

/*

* File: DieWithMessage.h

* Author: root

*

* Created on 2013年11月13日, 下午3:52

*/

#ifndef DIEWITHMESSAGE_H

#defineDIEWITHMESSAGE_H

#ifdef__cplusplus

extern "C" {

#endif

#include

#include

void DieWithUserMessage(const char *msg,const char * detail)

{

fputs(msg,stderr);

fputs(":",stderr);

fputs(detail,stderr);

fputs("\n",stderr);

exit(1);

}

void DieWithSystemMessage(const char* msg)

{

perror(msg);

exit(1);

}

#ifdef__cplusplus

}

#endif

#endif/* DIEWITHMESSAGE_H */

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值