1、使用socket()创建tcp套接字。
2、利用bind()给套接字分配端口号。
3、使用listen()告诉系统允许对该端口建立连接。
4、调用accept()为每个客户连接获取新的套接字。
5、使用send()和recv()通过新的套接字与客户端通信。
6、使用close()关闭客户连接。
1、主机字节序和网络字节序的转换
函数名中,h代表host,就是主机;n代表net 就是网络;l代表long是32位整数;s代表short是16位整数。
#include2、socket结构体uint32_t htonl(uint32_t hostlong); uint16_t htons(uint16_t hostshort); uint32_t ntohl(uint32_t netlong); uint16_t ntohs(uint16_t netshort);
IPv4和IPv6的地址格式定义在 netinet.h 中。在IPv4地址中使用sockaddr_in结构体,包括16位的端口号和32位的IP地址。IPv6地址使用sockaddr_in6结构体,包括16位的端口号和128位的ip地址和一些控制字段。
地址结构的第一部分定义了地址族——地址属于的空间。AF_INET和AF_INET6分别代表IPv6和IPv4的Internet地址族。
sockaddr 定义了一种泛型的数据类型,用于指定与套接字关联的地址。
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
};
struct in_addr {
uint32_t s_addr;
};
struct sockaddr_in {
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
char sin_zero[8];
}
struct in6_addr {
uint32_t s_addr[16];
};
struct sockaddr_in6 {
sa_family_t sin6_family;
in_port_t sin6_port;
uint32_t sin6_flowinfo;
struct in6_addr sin6_addr;
uint32_t sin6_scope_id;
};
3、二进制/字符串地址转换
// pton = printable to numeric
// addressFamily: 要转换地址的地址族
// src:转换的地址,字符串以null终止
// des:存放结果的地址空间
// 转换成功,返回1;未指定地址族,返回-1;des未格式化成指定类型,返回0。
int inet_pton(int addressFamily, const char *src, void *dst)
// addressFamily:要转换的地址类型。
// src:指向包含要转换的数字地址的内存块
// des:指向在调用这的空间中分配的缓冲区
const char *inet_ntop(int addressFamily, const void *src, char *dst, socklen_t desBytes)
// socket:是我们想要获得的地址信息的套接字描述符
// remoteAddress和localAddress :指向把地址信息存放在其中的地址结构
int getpeername(int socket, struct sockaddr *remoteAddress, socklen_t *addressLength)
int getsockname(int socket, struct sockaddr *localAddress, socklen_t *addressLength)
// domain:通信领域,IPv4(AF_INET), IPv6(AF_INET6)
// type:SOCK_STREAM表示利用可靠的自截留语义指定一个套接字。SOCK_DGRAM则指定一种"尽力而为"的数据报套接字
// protocal:指定要使用的指定的端到端协议;TCP(IPPROTO_TCP)、UCP(IPPROTO_UCP)
// 返回:-1表示失败;
int socket(int domain, int type, int protocal)
// 释放套接字。
// 返回:0代表成功,-1表示失败
int close(int socket)
int connect(int socket, const struct sockaddr *foreignAddress, socklen_t addressLength)
int bind(int socket, struct sockaddr *localAddress, socklen_t addressSize)
int listen(int socket, int queueLimit)
int accept(int socket, struct sockaddr *clientAddress, socklen_t *addressLength)
ssize_t send(int socket, const void *msg, size_t msgLength, int flags)
ssize_t recv(int socket, void *rcvBuffer, size_t bufferLength, int flags)
#include
#include
#include
#include
#include
#include
#include
static const int MAXPENDING = 5;
static const int BUFSIZE = 1024;
void HandleTCPClient(int clntSocket);
void DieWithUserMessage(const char *msg, const char *detail);
void DieWithSystemMessage(const char *msg);
int main(int argc, char *argv[]) {
if(argc != 2)
DieWithUserMessage("Parameter(s)", "");
in_port_t servPort = atoi(argv[1]);
// Create socket for incoming connections
int servSock;
if((servSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0 ) {
DieWithSystemMessage("Socket() failed");
}
// Construct local address structure
struct sockaddr_in servAddr; // Local address
memset(&servAddr, 0, sizeof(servAddr)); // Zero out structure
servAddr.sin_family = AF_INET; // IPv4 address family
servAddr.sin_addr.s_addr = htonl(INADDR_ANY); // Any incoming interface.
servAddr.sin_port = htons(servPort);
//Bind to the local address
if (bind(servSock, (struct sockaddr*) &servAddr, sizeof(servAddr)) < 0 )
DieWithSystemMessage("bind() failed");
// Mark the socket so it will listen for incoming connections
if (listen(servSock, MAXPENDING) < 0 )
DieWithSystemMessage("listen() failed");
for (;;) { // Run forever
struct sockaddr_in clntAddr; // Client address
// Set length of client address structure (in-out parameter)
socklen_t clntAddrLen = sizeof(clntAddr);
// Wait for a client to connect
int clntSock = accept(servSock, (struct sockaddr*) &clntAddr, &clntAddrLen);
if ( clntSock < 0 )
DieWithSystemMessage("accept() failed");
// clntSock is connected to a client!
char clntName[INET_ADDRSTRLEN]; // String to contain client address
if (inet_ntop(AF_INET, &clntAddr.sin_addr.s_addr, clntName, sizeof(clntName)) != NULL )
printf("Handling client %s/%d\n", clntName, ntohs(clntAddr.sin_port));
else
puts("Unable to get client address");
HandleTCPClient(clntSock);
}
}
void HandleTCPClient(int clntSocket){
char buffer[BUFSIZE]; // Buffer for echo string
// Receive message from client.
ssize_t numBytesRcvd = recv(clntSocket, buffer, BUFSIZE, 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()", "send unexpected number of bytes");
// See if there is more data to receive.
numBytesRcvd = recv(clntSocket, buffer, BUFSIZE, 0);
if ( numBytesRcvd < 0 )
DieWithSystemMessage("recv() failed.");
}
close(clntSocket); // Close client socket.
}
void DieWithUserMessage(const char *msg, const char *detail) {
fputs(msg, stderr);
fputs(": ", stderr);
fputs(detail, stderr);
fputc('\n', stderr);
exit(1);
}
void DieWithSystemMessage(const char *msg) {
perror(msg);
exit(1);
}
#include
#include
#include
#include
#include // IPPROTO_TCP
#include "DieMessage.h"
int main(int argc, char **argv){
if ( argc < 3) {
DieWithUserMessage("Parameter(s)", "[]");
}
// Create local socket
int sock;
if ( ( sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP ) ) < 0 ) {
DieWithSystemMessage("socket() failed.");
}
int servPort = atoi(argv[2]);
// Create server address
struct sockaddr_in servAddr;
memset( &servAddr, 0, sizeof(servAddr) );
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(servPort);
inet_pton(AF_INET, argv[1], &servAddr.sin_addr.s_addr);
// Connect to server
if ( (connect( sock, (struct sockaddr *) &servAddr, sizeof(servAddr))) < 0 ) {
DieWithSystemMessage("connect() failed.");
}
// Send Message to server
ssize_t sentByteLen = send( sock, argv[3], sizeof(argv[3]), 0);
if ( sentByteLen > 0 ) {
printf("send: %s\tbytes:%d\n", argv[3], sentByteLen);
} else {
DieWithSystemMessage("send() failed");
}
// Receive Message from server
char recvBuf[sentByteLen];
ssize_t recvByteLen = recv( sock, recvBuf, sentByteLen, 0);
if ( recvByteLen > 0 ) {
printf("recv: %s\tbytes:%d\n", recvBuf, recvByteLen);
} else {
DieWithSystemMessage("recv() failed");
}
close(sock);
printf("end!\n");
}