概述

工作中用到了Linux C的网络编程,最近就又复习了相关的知识,留于此处。

原理

Linux C网络编程知识分为服务端和客户端编程:

  • 服务端流程为:创建Socket-->绑定IP和端口-->启动监听-->等待客户端连接-->与客户端交互(读、写数据)-->关闭连接;
  • 客户端流程为:创建Socket-->连接服务端-->与服务端交互(读、写数据)-->关闭连接;

代码

  • 服务端代码(server.c)
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])
{
// check argv
if (argc != 2)
{
printf("using: ./Server port\n");
return -1;
}

// create socket server
int listenFd;
if ((listenFd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket");
return -1;
}

// bind
struct sockaddr_in serverAddr;
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddr.sin_port = htons(atoi(argv[1]));
if (bind(listenFd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) != 0)
{
perror("bind");
return -1;
}

// listen
if (listen(listenFd, 5) != 0)
{
perror("listen");
close(listenFd);
return -1;
}

// accept
int clientFd;
int socklen = sizeof(struct sockaddr_in);
struct sockaddr_in clientAddr;
clientFd = accept(listenFd, (struct sockaddr_in *)&clientAddr, (socklen_t *)&socklen);
printf("客户端已连接...\n");

// send recv
char buffer[1024];
while (1)
{
int nRet;
memset(buffer, 0, sizeof(buffer));
if ((nRet = recv(clientFd, buffer, sizeof(buffer), 0)) <= 0)
{
printf("recv ret=%d\n", nRet);
break;
}
printf("接收: %s\n", buffer);

strcpy(buffer, "Ok");
if ((nRet = send(clientFd, buffer, strlen(buffer), 0)) <= 0)
{
perror("send");
break;
}
printf("发送: %s\n", buffer);
}

close(listenFd);
close(clientFd);
}
  • 客户端代码(client.c)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main( int argc, char* argv[] )
{
//check
if( argc != 3 )
{
printf( "Using: ./client ip port\n" );
return -1;
}

//create socket
int sockFd;
if( ( sockFd = socket( AF_INET,SOCK_STREAM, 0 ) ) == -1 )
{
perror( "socket" );
return -1;
}
printf( "create socket finished\n" );

//connect
struct hostent* pHost;
if( ( pHost = gethostbyname( argv[1] ) ) == 0 )
{
printf( "gethostbyname failed! \n" );
close( sockFd );
return -1;
}
printf( "gethostbyname finished\n" );

struct sockaddr_in serverAddr;
memset( &serverAddr, 0, sizeof( serverAddr ) );
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons( atoi( argv[2] ) );
printf( "sin_port finished\n" );
memcpy( &serverAddr.sin_addr, pHost->h_addr, pHost->h_length );
memcpy( &serverAddr.sin_addr, pHost->h_addr, pHost->h_length );
printf( "sin_addr finished\n" );
if( connect( sockFd, ( struct sockaddr* )&serverAddr, sizeof( serverAddr ) ) != 0 )
{
perror( "connect" );
close( sockFd );
return -1;
}
printf( "connect finished\n" );

//send recv
char buffer[ 1024 ];
for( int n = 0; n < 3; n++ )
{
int nRet;
memset( buffer, 0, sizeof( buffer ) );
sprintf( buffer, "%d--啊哈哈哈哈", n+1 );
if( ( nRet = send( sockFd, buffer, strlen( buffer ), 0 ) ) <= 0 )
{
perror( "send" );
close( sockFd );
return -1;
}
printf( "发送:%s\n", buffer );

memset( buffer, 0, sizeof( buffer ) );
if( ( nRet = recv( sockFd, buffer, sizeof( buffer ), 0 ) ) <= 0 )
{
printf( "recv ret=%d\n", nRet );
break;
}
printf( "接收:%s\n", buffer );
}

//close
close( sockFd );
}

编译代码

gcc -o server server.c
gcc -o client client.c