Следующая программа на языке c ++ должна преобразовывать каждую строку в верхний регистр с помощью дейтаграммы сокета для связи между двумя потоками.
Example:
Hello World!<return>
HELLO WORLD!
123abc!<return>
123ABC!
<return>
<end program>
Программа, как написано, работает для меня, однако, если я прокомментирую вызов функции bugfix()
вОсновная программа ждет бесконечно после первой строки ввода.
Example:
Hello World!<return>
<the program wait indefinitely>
Это происходит в Windows 7 с последним обновлением от 10.04.2011 с использованием последнего MinGW32.
#include <iostream>
#include <cstdlib>
#include <cctype>
#include <sys/types.h>
#include <winsock.h>
#include <windows.h>
#include <process.h>
using namespace std;
#define CHECK(exp, cond) do { typeof(exp) _check_value_ = exp; check(_check_value_ cond, _check_value_, __LINE__, #exp #cond); } while(0)
template <class T>
void check(bool ok, T value, int line, const char* text) {
if (!ok) {
cerr << "ERROR(" << line << "):" << text << "\nReturned: " << value << endl;
cerr << "errno=" << errno << endl;
cerr << "WSAGetLastError()=" << WSAGetLastError() << endl;
exit(EXIT_FAILURE);
}
}
#define DATA_CAPACITY 1000
#define PORT 23584
#define TEST_IP "192.0.32.10"
#define MYSELF "127.0.0.1"
#define DST_IP MYSELF
sockaddr_in address(u_long ip, u_short port) {
sockaddr_in addr = { };
addr.sin_family = AF_INET;
addr.sin_port = port;
addr.sin_addr.s_addr = ip;
return addr;
}
void __cdecl client_thread(void* args) {
SOCKET s = *(SOCKET*)args;
sockaddr_in addr = address(inet_addr(DST_IP), htons(PORT));
char data[DATA_CAPACITY];
while (1) {
cin.getline(data, DATA_CAPACITY);
int data_len = strlen(data);
CHECK(sendto(s, data, data_len, 0, (sockaddr*)&addr, sizeof addr), >= 0);
CHECK(recvfrom(s, data, DATA_CAPACITY, 0, NULL, NULL), >= 0);
cout << data << endl;
if (data_len == 0)
break;
}
CHECK(closesocket(s), == 0);
}
void __cdecl server_thread(void* args) {
SOCKET s = *(SOCKET*)args;
sockaddr_in addr = address(INADDR_ANY, htons(PORT));
int addr_size = sizeof addr;
CHECK(bind(s, (sockaddr*)&addr, sizeof addr), != SOCKET_ERROR);
char data[DATA_CAPACITY];
while (1) {
int data_len = recvfrom(s, data, DATA_CAPACITY, 0, (sockaddr*)&addr, &addr_size);
CHECK(data_len, >= 0);
for (int i = 0; i < data_len; i++)
if (islower(data[i]))
data[i] = toupper(data[i]);
CHECK(sendto(s, data, data_len, 0, (sockaddr*)&addr, addr_size), >= 0);
if (data_len == 0)
break;
}
CHECK(closesocket(s), == 0);
}
// This function create a TCP connection with www.example.com and the close it
void bugfix() {
SOCKET s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in addr = address(inet_addr(TEST_IP), htons(80));
connect(s, (sockaddr*)&addr, sizeof addr);
CHECK(closesocket(s), == 0);
}
int main()
{
cout << "Convert text to uppercase, an empty line terminate the program" << endl;
WSADATA wsaData;
CHECK(WSAStartup(MAKEWORD(2, 2), &wsaData), == 0);
SOCKET client = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
SOCKET server = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
CHECK(client, != INVALID_SOCKET);
CHECK(server, != INVALID_SOCKET);
// if this function is not called the program doesn't work
bugfix();
HANDLE hClient = (HANDLE)_beginthread(client_thread, 0, &client);
HANDLE hServer = (HANDLE)_beginthread(server_thread, 0, &server);
HANDLE h[] = { hClient, hServer };
WaitForMultipleObjects(sizeof h / sizeof *h, h, TRUE, INFINITE);
CHECK(WSACleanup(), == 0);
return EXIT_SUCCESS;
}