《TCP/IP网络编程》第2章 套接字类型与协议设置

92 篇文章 18 订阅
34 篇文章 3 订阅

#include <sys/socket.h>
//成功文件描述符,失败-1
int socket(int domain, int type, int protocol);

协议族(Protocal Family)

PF_INET,IPv4
PF_INET6,IPv6
PF_LOCAL,本地UNIX
PF_PACKET,底层套接字
PF_IPX,IPX Novell

套接字类型(Type)

套接字的数据传输方式。

  • SOCK_STREAM,面向连接
    数据不会消失,可靠;
    按序传输,有序;
    无数据边界(Boundary),基于字节,read()和write()并不一定一致(内部缓冲);
    套接字一一对应。
int tcp_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
  • SOCK_DGRAM,面向消息
    数据可能丢失或损毁,不可靠;
    快速而非有序传输,无序高速;
    有数据边界,read()和write()一致(一次传输一次接收);
    限制每次传输数据大小;
int udp_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);

TCP客户端

02.tcp_client_linux.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define IP "127.0.0.1"
#define PORT 9999

void error_handling(char *message)
{
	fputs(message, stderr);
	fputc('\n', stderr);
	exit(1);
}

int main(int argc, char *argv[])
{
	int sock = socket(PF_INET, SOCK_STREAM, 0);
	if (sock == -1)
		error_handling("socket() error");

	socklen_t addr_size = sizeof(struct sockaddr_in);

	struct sockaddr_in addr;
	memset(&addr, 0, addr_size);
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = inet_addr(IP);
	addr.sin_port = htons(PORT);

	if (connect(sock, (struct sockaddr *)&addr, addr_size) == -1)
		error_handling("connect() error");

	int read_len;
	int str_len = 0;
	char message[30];
	for (int idx = 0; read_len = read(sock, &message[idx], 1); idx++)
	{
		if (read_len == -1)
			error_handling("read() error");
		str_len += read_len;
	}
	message[str_len] = '\0';

	printf("Message from server: %s \n", message);
	printf("Function read call count: %d \n", str_len);

	close(sock);

	return 0;
}

// gcc tcp_client.c -o tcp_client
// ./tcp_client

Windows平台

#include <winsock2.h>
//成功返回套接字句柄,失败INVALID_SOCKET
SOCKET socket(int af, int type, int protocol);

客户端

02.tcp_client_win.c
#include <stdio.h>
#include <winsock2.h>

#define IP "127.0.0.1"
#define PORT 9999

void ErrorHanding(const char *message)
{
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

int main(int argc, char *argv[])
{
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
        ErrorHanding("WSAStartup() error!");

    SOCKET hSock = socket(PF_INET, SOCK_STREAM, 0);
    if (hSock == INVALID_SOCKET)
        ErrorHanding("socket() error!");

    const int szAddr = sizeof(SOCKADDR_IN);

    SOCKADDR_IN servAddr;
    memset(&servAddr, 0, szAddr);
    servAddr.sin_family = AF_INET;
    servAddr.sin_addr.s_addr = inet_addr(IP);
    servAddr.sin_port = htons(PORT);

    if (connect(hSock, (SOCKADDR *)&servAddr, szAddr) == SOCKET_ERROR)
        ErrorHanding("connect() error!");

    int strLen = 0;

    int readLen;
    char message[30];
    int idx = 0; 
    for (; readLen = recv(hSock, &message[idx], 1, 0); idx++)
    {
        if (readLen == -1)
            ErrorHanding("recv() error!");
        strLen += readLen;
    }
    message[strLen] = '\0';
    printf("Message from server: %s\n", message);
    printf("Function recv call count: %d\n", idx);

    closesocket(hSock);

    WSACleanup();

    return 0;
}

// gcc 02.tcp_client_win.c -o 02.tcp_client_win -lws2_32 && 02.tcp_client_win
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值