C言語ネットワークプログラミング(2)-TCP通信
1. TCPクライアント
1.接続の確立
ソケットを使用したいので、まず、使用するヘッダーファイルを追加します。
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
TCPソケット、ipv4プロトコルを作成し、SOCK_STREAMパラメータを使用します。プロトコルは0で、デフォルトで自動的にTCPプロトコルを選択します。
// 1、使用socket()函数获取一个socket文件描述符
int tcp_client = socket(AF_INET, SOCK_STREAM, 0);
次に、サーバーのIPアドレスとポート番号を構造体に入れて準備します
// 2、准备服务端的地址和端口,'192.168.0.107'表示目的ip地址,12341表示目的端口号
struct sockaddr_in server_addr = {0};
server_addr.sin_family = AF_INET; // 设置地址族为IPv4
server_addr.sin_port = htons(12341); // 设置地址的端口号信息
server_addr.sin_addr.s_addr = inet_addr("192.168.0.107"); // 设置IP地址
次に、connectメソッドを使用して接続します。接続が成功した場合は0を返します。失敗した場合は-1を返します
// 3、链接到服务器
ret = connect(tcp_client, (const struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret < 0)
perror("connect");
else
printf("connect result, ret = %d.\n", ret);
最後に、ソケットを閉じることを忘れないでください
// 4、关闭套接字
close(tcp_client);
コンパイルして実行すると、接続は成功します:
2、データ
を送信しますsend()関数を使用してデータを送信します
// 4. 发送数据到服务端
char sendbuf[]={"hello world."};
ret = send(sockfd, sendbuf, strlen(sendbuf),0);
データが正常に送信され、サーバーがデータを受信したことがわかります。3
。データを受信する
場合は、recv関数を使用して受信を待機できます。そのパラメーターは受信された最大バイト数であり、受信されたデータが出力されます。出てくる
完全なコードは次のとおりです。
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
int main(void)
{
int ret;
// 1、使用socket()函数获取一个TCP客户端socket文件描述符
int tcp_client = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == tcp_client)
{
perror("socket");
return -1;
}
// 2、准备服务端的地址和端口,'192.168.0.107'表示目的ip地址,12341表示目的端口号
struct sockaddr_in server_addr = {0};
server_addr.sin_family = AF_INET; // 设置地址族为IPv4
server_addr.sin_port = htons(12341); // 设置地址的端口号信息
server_addr.sin_addr.s_addr = inet_addr("192.168.0.107"); // 设置IP地址
// 3、链接到服务器
ret = connect(tcp_client, (const struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret < 0)
perror("connect");
else
printf("connect result, ret = %d.\n", ret);
// 4. 发送数据到服务端
char sendbuf[]={"hello world."};
ret = send(tcp_client, sendbuf, strlen(sendbuf),0);
// 5、等待接收服务端发送过来的数据,最大接收1024个字节
char recvbuf[1024] = {0};
ret = recv(tcp_client, recvbuf, sizeof(recvbuf), 0);
// 6、将接收到的数据打印出来
printf("Recvdate:%s \n",recvbuf);
// 7、关闭套接字
close(tcp_client);
}
第二に、TCPサーバー
1.サーバーを確立し、接続を待機します。
同様に、ソケットを使用します。最初に、使用するヘッダーファイルを追加します。
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
TCPソケット、ipv4プロトコルを作成し、SOCK_STREAMパラメータを使用します。プロトコルは0で、デフォルトで自動的にTCPプロトコルを選択します。
// 1、使用socket()函数获取一个socket文件描述符
int tcp_server = socket(AF_INET, SOCK_STREAM, 0);
クライアントがそれに接続するために、ポート番号をバインドする必要があります
// 2. 绑定本地的相关信息,如果不绑定,则系统会随机分配一个端口号
struct sockaddr_in local_addr = {0};
local_addr.sin_family = AF_INET; // 设置地址族为IPv4
local_addr.sin_port = htons(8266); // 设置地址的端口号信息
local_addr.sin_addr.s_addr = inet_addr("192.168.0.107"); // 设置IP地址
ret = bind(tcp_server, (const struct sockaddr *)&local_addr, sizeof(local_addr));
if (ret < 0)
perror("bind");
else
printf("bind success.\n");
次に、listenメソッドを使用して接続をリッスンできます。2番目のパラメータは、待機できるキューに入れられた接続の数です
// 3、listen监听端口,阻塞,等待客户端来连接服务器
ret = listen(sockfd, 5);
acceptメソッドを使用して、クライアントがこのサーバーに接続するのを待ちます。戻り値は、接続されたクライアントのソケットファイル記述子です。
// 4、accept阻塞等待客户端接入
struct sockaddr_in client_addr;
socklen_t addrlen = sizeof(client_addr);
int client_fd = accept(tcp_server, (struct sockaddr *)&client_addr, &addrlen);
リンクされているクライアント情報を印刷します
// 5、打印连接过来的客户端信息及其ip地址
printf("Client from %s:%d \n",inet_ntoa(*(struct in_addr*)&client_addr.sin_addr.s_addr),ntohs(client_addr.sin_port));
その後、ソケットを閉じることができます
// 6、关闭套接字
close(tcp_client);
プログラムを実行し、ネットワークデバッグアシスタントを使用して接続します。接続が成功したことがわかります
。2.データを受信します。
クライアントが接続すると、クライアントソケットファイル記述子を使用して、相手から送信されるデータを待機できます。
// 5、等待接收对方发送过来的数据
char recvbuf[1024] = {0};
ret = recv(client_fd, recvbuf, sizeof(recvbuf), 0);
printf("Recv from %s:%d, ",inet_ntoa(*(struct in_addr*)&client_addr.sin_addr.s_addr),ntohs(client_addr.sin_port));
printf("recv_data: %s \n",recvbuf);
ネットワークデバッグアシスタントクライアントをコンパイル、実行、および使用してデータを送信します。結果は次のとおりです
。3.データの送信データを
受信したら、データを送信してクライアントにデータを受信したことを通知します
// 6、返回数据到客户端
char send_buf[1024] = "I have got the date:";
strcat(send_buf,recvbuf);
send(client_fd, send_buf, strlen(send_buf), 0);
結果の
完了コードをコンパイルして実行する
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
int main(void)
{
int ret = -1;
// 1、使用socket()函数获取一个socket文件描述符
int tcp_server = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == tcp_server)
{
perror("socket");
return -1;
}
// 2. 绑定本地的相关信息,如果不绑定,则系统会随机分配一个端口号
struct sockaddr_in local_addr = {0};
local_addr.sin_family = AF_INET; // 设置地址族为IPv4
local_addr.sin_port = htons(8266); // 设置地址的端口号信息
local_addr.sin_addr.s_addr = inet_addr("192.168.0.107"); // 设置IP地址
ret = bind(tcp_server, (const struct sockaddr *)&local_addr, sizeof(local_addr));
if (ret < 0)
perror("bind");
else
printf("bind success.\n");
// 3、listen监听端口,阻塞,等待客户端来连接服务器
ret = listen(tcp_server, 5);
// 4、accept阻塞等待客户端接入
struct sockaddr_in client_addr;
socklen_t addrlen = sizeof(client_addr);
int client_fd = accept(tcp_server, (struct sockaddr *)&client_addr, &addrlen);
// 5、等待接收对方发送过来的数据
char recvbuf[1024] = {0};
ret = recv(client_fd, recvbuf, sizeof(recvbuf), 0);
printf("Recv from %s:%d, ",inet_ntoa(*(struct in_addr*)&client_addr.sin_addr.s_addr),ntohs(client_addr.sin_port));
printf("recv_data: %s \n",recvbuf);
// 6、返回数据到客户端
char send_buf[1024] = "I have got the date:";
strcat(send_buf,recvbuf);
send(client_fd, send_buf, strlen(send_buf), 0);
// 7、关闭套接字
close(tcp_server);
}