Steward
分享是一種喜悅、更是一種幸福
程式語言 - MinGW - C/C++ - Console - TCP Server、Client
參考資訊:
https://www.geeksforgeeks.org/socket-programming-cc/
server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <ws2tcpip.h>
int main(int argc, char *argv[])
{
int r = 0;
int opt = 1;
SOCKET fd = INVALID_SOCKET;
SOCKET new_socket = INVALID_SOCKET;
char buf[255] = { 0 };
char client_ip[INET_ADDRSTRLEN] = { 0};
struct sockaddr_in addr = { 0 };
struct sockaddr_in client_addr = { 0 };
int addrlen = sizeof(client_addr);
const char *hello = "hello from server !";
WSADATA wsaData = { 0 };
if (argc != 3) {
printf("Usage: %s IP Port\n", argv[0]);
return 0;
}
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
printf("WSAStartup failed: %d\n", WSAGetLastError());
return 1;
}
fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (fd == INVALID_SOCKET) {
printf("socket() failed: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof(opt)) == SOCKET_ERROR) {
printf("setsockopt() failed: %d\n", WSAGetLastError());
closesocket(fd);
WSACleanup();
return 1;
}
addr.sin_family = AF_INET;
addr.sin_port = htons((u_short)atoi(argv[2]));
if (InetPtonA(AF_INET, argv[1], &addr.sin_addr) != 1) {
printf("Invalid IP address: %s\n", argv[1]);
closesocket(fd);
WSACleanup();
return 1;
}
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR) {
printf("bind() failed: %d\n", WSAGetLastError());
closesocket(fd);
WSACleanup();
return 1;
}
if (listen(fd, 3) == SOCKET_ERROR) {
printf("listen() failed: %d\n", WSAGetLastError());
closesocket(fd);
WSACleanup();
return 1;
}
printf("Server listening on %s:%s\n", argv[1], argv[2]);
new_socket = accept(fd, (struct sockaddr *)&client_addr, &addrlen);
if (new_socket == INVALID_SOCKET) {
printf("accept() failed: %d\n", WSAGetLastError());
closesocket(fd);
WSACleanup();
return 1;
}
if (InetNtopA(AF_INET, &client_addr.sin_addr, client_ip, sizeof(client_ip))) {
printf("Client connected from %s:%u\n", client_ip, ntohs(client_addr.sin_port));
}
r = recv(new_socket, buf, sizeof(buf) - 1, 0);
if (r == SOCKET_ERROR) {
printf("recv() failed: %d\n", WSAGetLastError());
} else if (r == 0) {
printf("Client closed connection\n");
} else {
buf[r] = '\0';
printf("%s (r=%d)\n", buf, r);
}
if (r > 0) {
r = send(new_socket, hello, (int)strlen(hello), 0);
if (r == SOCKET_ERROR) {
printf("send() failed: %d\n", WSAGetLastError());
}
}
closesocket(new_socket);
closesocket(fd);
WSACleanup();
return 0;
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <ws2tcpip.h>
int main(int argc, char *argv[])
{
int r = 0;
SOCKET fd = INVALID_SOCKET;
char buf[255] = { 0 };
struct sockaddr_in addr = { 0 };
const char *hello = "hello from client !";
WSADATA wsaData;
if (argc != 3) {
printf("Usage: %s IP Port\n", argv[0]);
return 0;
}
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
printf("WSAStartup failed: %d\n", WSAGetLastError());
return 1;
}
fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (fd == INVALID_SOCKET) {
printf("socket() failed: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
addr.sin_family = AF_INET;
addr.sin_port = htons((u_short)atoi(argv[2]));
if (InetPtonA(AF_INET, argv[1], &addr.sin_addr) != 1) {
printf("Invalid IP address: %s\n", argv[1]);
closesocket(fd);
WSACleanup();
return 1;
}
if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR) {
printf("connect() failed: %d\n", WSAGetLastError());
closesocket(fd);
WSACleanup();
return 1;
}
printf("Connected to %s:%s\n", argv[1], argv[2]);
r = send(fd, hello, (int)strlen(hello), 0);
if (r == SOCKET_ERROR) {
printf("send() failed: %d\n", WSAGetLastError());
closesocket(fd);
WSACleanup();
return 1;
}
printf("Sent %d bytes\n", r);
r = recv(fd, buf, sizeof(buf) - 1, 0);
if (r == SOCKET_ERROR) {
printf("recv() failed: %d\n", WSAGetLastError());
}
else if (r == 0) {
printf("Server closed connection\n");
}
else {
buf[r] = '\0';
printf("%s (r=%d)\n", buf, r);
}
closesocket(fd);
WSACleanup();
return 0;
}
編譯、執行
$ i686-w64-mingw32-gcc server_win32.c -o server_win32.exe -lws2_32
$ i686-w64-mingw32-gcc client_win32.c -o client_win32.exe -lws2_32
$ ./server_win32.exe 127.0.0.1 8888
Server listening on 127.0.0.1:8888
$ ./client.exe 127.0.0.1 9999
Connected to 127.0.0.1:9999
Sent 19 bytes
hello from server ! (r=19)
Client connected from 127.0.0.1:38460
hello from client ! (r=19)